<template>
	<div class="error-boundary">
		<div v-if="hasError" class="error-message">
			<h3>{{ $t('report.pageError') }}</h3>
			<p>{{ errorMessage }}</p>
			<button @click="reloadPage" class="reload-btn">{{ $t('report.reload') }}</button>
		</div>
		<div v-else-if="!infoData || !infoData.user" class="loading-message">
			<p>{{ $t('report.dataLoading') }}</p>
			<p style="font-size: 12px; color: #666; margin-top: 10px;">
			</p>
		</div>
		<div v-else class="report-bg" v-if="infoData && infoData.user">
			<div class="report-main" ref="reportMainRef" @mousedown="handleMouseDown" :class="{ 'dragging': isDragging }">
				<!-- 缩放时的滚动条指示器 -->
				<div v-if="tableScale > 1" class="scroll-indicator">
					<div class="scroll-indicator-text">可滚动查看</div>
				</div>
				<div class="report-content" :style="{ transform: `scale(${tableScale})`, transformOrigin: 'left top' }">
					<div v-if="showUnitName" class="unit-name">{{ unitName }}</div>
					<div class="report-title">{{ $t('report.title') }}</div>
					<div class="block">
						<div class="block-title">{{ $t('report.personalInfo') }}</div>
						<div class="info-row">
							<div class="info-item fix-width"><span class="label">{{ $t('common.name') }}：</span><input class="input"
									:value="infoData.user.name" readonly /></div>
							<div class="info-item fix-width"><span class="label">{{ $t('common.age') }}：</span><input class="input"
									:value="infoData.user.age" />
							</div>
						</div>
						<div class="info-row u-f">
							<div class="info-item fix-width"><span class="label">{{ $t('common.gender') }}：</span>
								<span class="radio checked" v-if="infoData.user.sex == '0'">●{{ $t('common.male') }} </span>
								<span class="radio" v-else>○{{ $t('common.male') }}</span>

								<span class="radio checked" v-if="infoData.user.sex == '1'">●{{ $t('common.female') }} </span>
								<span class="radio" v-else>○{{ $t('common.female') }}</span>
							</div>
							<div class="info-item fix-width"><span class="label">{{ $t('common.id') }}：</span><input class="input id-input"
									:value="infoData.user.anamnesisid" readonly style="border: none !important; " /></div>

						</div>
						<div class="info-row">
						</div>
					</div>
					<div class="block">
						<div class="block-title">{{ $t('report.assessmentInfo') }}</div>
						<div class="info-row">
							<div class="info-item fix-width-100"><span class="label">{{ $t('report.assessmentScale') }}：</span>{{
								infoData.gameName }}</div>
							<!-- <div class="info-item fix-width"><span class="label">训练时长：</span>01:00</div> -->
						</div>
						<div class="info-row" style="justify-content: space-between;">
							<div class="info-item fix-width-30"><span class="label">{{ $t('report.assessmentDate') }}：</span>{{
								formatTime(infoData.startTime, 'yyyy-MM-dd') }}</div>
							<div class="info-item fix-width-30"><span class="label">{{ $t('report.startTime') }}：</span>{{
								formatTime(infoData.startTime, 'HH:mm:ss') }}</div>
							<div class="info-item fix-width-30"><span class="label">{{ $t('report.endTime') }}：</span>{{
								formatTime(infoData.endTime, 'HH:mm:ss') }}</div>

						</div>

					</div>
					<div class="table-area u-f-a" style="text-align: left;">
						<table class="custom-table">
							<thead>
								<tr>
									<th style="width: 60px;text-align: center;">{{ $t('report.serialNumber') }}</th>
									<th style="text-align: center;">{{ $t('report.assessmentContent') }}</th>
									<th style="width: 90px;text-align: center;">{{ $t('report.assessmentScore') }}</th>
									<th style="width: 150px;text-align: center;">{{ $t('report.remarks') }}</th>
								</tr>
							</thead>
							<tbody>
								<!-- type.questionList && type.questionList.length
													? type.questionList.reduce((sum: any, q: any) => {
														if (q.options && q.options.length) {
															// 累加所有选中选项的分数
															const selectedScore = q.options.filter((o:any) => o.isSelected).reduce((optSum:number, o:any) => optSum + (Number(o.score) || 0), 0);
															return sum + selectedScore;
														}
														return sum;
													}, 0)
													: -->
								<template v-for="(type, typeIdx) in (infoData.questionTypeList || [])" :key="typeIdx">
									<!-- 一级大题：如果有子题列表或者没有options，显示为标题行 -->
									<tr
										v-if="(type.questionType || type.title) && ((type.questionList && type.questionList.length > 0) || (!type.options || type.options.length === 0))">
										<td style="text-align: center;">{{ typeIdx + 1 }}</td>
										<td style="text-align: left;padding-left:20px;">{{ type.questionType || type.title }}</td>
										<td style="text-align: center;" class="score">
											<!-- 一级大题不显示分数 -->
										</td>
										<td style="text-align: center;">
											<div v-if="type.audio" class="audio-controls">
												<button class="audio-btn" @click="toggleAudio(type.audio, `type-${typeIdx}`)"
													:disabled="isLoading[`type-${typeIdx}`]">
													<i class="iconfont"
														:class="currentPlaying === `type-${typeIdx}` ? 'icon-zanting' : 'icon-bofang'"></i>
												</button>
											</div>
											<span v-else></span>
										</td>
									</tr>
									<!-- 一级大题作为答题行：如果没有子题但有options -->
									<tr
										v-else-if="(type.questionType || type.title) && (!type.questionList || type.questionList.length === 0) && type.options && type.options.length > 0">
										<td style="text-align: center;">{{ typeIdx + 1 }}</td>
										<td style="text-align: left;padding-left:20px;">{{ type.questionType || type.title }}</td>
										<td style="text-align: center;">
											{{ getSelectedScore(type.options) || type.score || '0' }}
										</td>
										<td style="text-align: center;">
											<div v-if="type.audio" class="audio-controls">
												<button class="audio-btn" @click="toggleAudio(type.audio, `type-${typeIdx}`)"
													:disabled="isLoading[`type-${typeIdx}`]">
													<i class="iconfont"
														:class="currentPlaying === `type-${typeIdx}` ? 'icon-zanting' : 'icon-bofang'"></i>
												</button>
											</div>
											<span v-else></span>
										</td>
									</tr>
									<!-- 二级题目 -->
									<template v-for="(q, qIdx) in type.questionList" :key="qIdx + '-' + typeIdx">
										<!-- 有第三级子题的情况 -->
										<template v-if="q.questionList && q.questionList.length > 0">
											<!-- 二级题目标题 -->
											<tr v-if="q.title">
												<td style="text-align: center !important;">{{ typeIdx + 1 }}.{{ qIdx + 1 }}</td>
												<td style="text-align: left;padding-left: 50px;">{{ q.title }}</td>
												<td style="text-align: center;">
													<!-- 有三级子题时，二级题目不显示分数 -->
												</td>
												<td style="text-align: center;">
													<div class="remark-content u-f-ajc" style="flex-direction: row;">
														<div v-if="q.canvasName" class="canvas-name">{{ q.canvasName }}</div>
														<div v-if="q.audio" class="audio-controls">
															<button class="audio-btn" @click="toggleAudio(q.audio, `${typeIdx}-${qIdx}`)"
																:disabled="isLoading[`${typeIdx}-${qIdx}`]">
																<i class="iconfont"
																	:class="currentPlaying === `${typeIdx}-${qIdx}` ? 'icon-zanting' : 'icon-bofang'"></i>
															</button>
														</div>
													</div>
												</td>
											</tr>
											<!-- 三级子题 -->
											<template v-for="(subQ, subIdx) in q.questionList" :key="`${typeIdx}-${qIdx}-${subIdx}`">
												<tr v-if="subQ.title">
													<td style="text-align: center !important;">{{ typeIdx + 1 }}.{{ qIdx + 1 }}.{{ subIdx + 1 }}
													</td>
													<td style="text-align: left;padding-left: 80px;">{{ subQ.title }}</td>
													<td style="text-align: center;">
														{{ getSelectedScore(subQ.options) || subQ.score || '' }}
													</td>
													<td style="text-align: center;">
														<div class="remark-content u-f-ajc" style="flex-direction: row;">
															<div v-if="subQ.canvasName" class="canvas-name">{{ subQ.canvasName }}</div>
															<div v-if="subQ.audio" class="audio-controls">
																<button class="audio-btn"
																	@click="toggleAudio(subQ.audio, `${typeIdx}-${qIdx}-${subIdx}`)"
																	:disabled="isLoading[`${typeIdx}-${qIdx}-${subIdx}`]">
																	<i class="iconfont"
																		:class="currentPlaying === `${typeIdx}-${qIdx}-${subIdx}` ? 'icon-zanting' : 'icon-bofang'"></i>
																</button>
															</div>
														</div>
													</td>
												</tr>
											</template>
										</template>
										<!-- 没有第三级子题的情况（原来的二级题目） -->
										<tr v-else-if="q.title">
											<td style="text-align: center !important;">{{ typeIdx + 1 }}.{{ qIdx + 1 }}</td>
											<td style="text-align: left;padding-left: 50px;">{{ q.title }}</td>
											<td style="text-align: center;">
												{{ getSelectedScore(q.options) || q.score || '' }}
											</td>
											<td style="text-align: center;">
												<div class="remark-content u-f-ajc" style="flex-direction: row;">
													<div v-if="q.canvasName" class="canvas-name">{{ q.canvasName }}</div>
													<div v-if="q.audio" class="audio-controls">
														<button class="audio-btn" @click="toggleAudio(q.audio, `${typeIdx}-${qIdx}`)"
															:disabled="isLoading[`${typeIdx}-${qIdx}`]">
															<i class="iconfont"
																:class="currentPlaying === `${typeIdx}-${qIdx}` ? 'icon-zanting' : 'icon-bofang'"></i>
														</button>
													</div>
												</div>
											</td>
										</tr>
									</template>
								</template>
							</tbody>
						</table>
					</div>

					<div class="block" style="margin-top: 20px;"
						v-show="infoData.horizontalAxis && infoData.horizontalAxis.length">
						<div class="block-title">{{ $t('report.chartAnalysis') }} <span v-if="infoData.charTitle">-> {{
							infoData.charTitle
						}}</span> </div>
						<div class="chart-area">
							<div class="echart-box" ref="timeChartRef"></div>
							<!-- <div class="echart-box" ref="resultChartRef"></div> -->
						</div>
					</div>
					<div class="score">
						<div class="u-f-ajsb " style="margin-bottom: 20px;" v-if="infoData.showTotalScore">
							<div>{{ $t('report.totalScore') }}：</div>
							<div>{{ getTotalScore() }}{{ $t('common.score') }}</div>
						</div>
						<div style="color: #999;font-size: 15px;text-align: left;" v-html="infoData.scoreDesc"></div>

					</div>
					<div class="block">
								<button class="u-f-ac theme-btn-primary" style="margin-left: auto;height: 30px;margin-bottom: 10px;
		border-radius: 50px;" @click="setDefault">{{ $t('report.preset') }}</button>
						<div class="info-row align-top">
							<div class="info-item opinion-box">
								<span class="label">{{ $t('report.opinion') }}：</span>
								<textarea class="opinion-input" rows="2" v-model="assessAdvice" />
							</div>

						</div>
						<div class="info-item sign-box" style="margin-top: 30px;">
							<span class="label" style="margin-left: auto;">{{ $t('report.signature') }}：</span>
							<input class="signature-input" type="text"
								style="border: none;border-bottom: 2px solid #2176b8 !important;margin-right: 30px;padding-bottom: 8px;font-size: 16px;font-weight: 500;"
								v-model="therapistSignature" />
						</div>

					</div>
					<div class="block-title" v-if="infoData.showAttachment && hasCanvasData" style="margin: 30px;">{{ $t('report.attachment') }}
					</div>
					<div class="images u-f-c" v-if="infoData.showAttachment && hasCanvasData">
						<template v-for="(type, typeIdx) in (infoData.questionTypeList || [])" :key="typeIdx">
							<template v-for="(item, itemIdx) in type.questionList" :key="`${typeIdx}-${itemIdx}`">
								<!-- 二级题目的canvas -->
								<div v-if="item.canvas" class="image-item">
									<div class="image-name">{{ item.canvasName }}</div>
									<img :src="item.canvas" :alt="item.canvasName" class="canvas-image" />
								</div>
								<!-- 三级子题的canvas -->
								<template v-if="item.questionList && item.questionList.length > 0">
									<template v-for="(subItem, subIdx) in item.questionList" :key="`${typeIdx}-${itemIdx}-${subIdx}`">
										<div v-if="subItem.canvas" class="image-item">
											<div class="image-name">{{ subItem.canvasName }}</div>
											<img :src="subItem.canvas" :alt="subItem.canvasName" class="canvas-image" />
										</div>
									</template>
								</template>
							</template>
						</template>
					</div>
				</div>

			</div>
			<div class="right-btns">
				<button class="right-btn" @click="() => savePdf()">{{ $t('common.save') }}</button>
				<button class="right-btn" @click="printReport">{{ $t('common.print') }}</button>
				<button class="right-btn" @click="exitReport">{{ $t('common.exit') }}</button>
			</div>
			<div class="zoom-float-bar">
				<span class="zoom-label">{{ $t('report.zoom') }}：</span>
				<input type="range" min="0.5" max="2" step="0.01" v-model.number="tableScale" />
				<span class="zoom-value">{{ (tableScale * 100).toFixed(0) }}%</span>
			</div>
			<Dialog ref="orderRef" @close="closeEmpty" isClose>
				<div style="width: 50vw;">
					<div style="color: #000;font-size: 22px;margin-top: 20px;">{{ $t('report.preset') }}</div>
					<div class="def">
						<div class="def-input-row u-f-ac">
							<div class="def-input-col ">
								<div class="def-input-label" style="text-align: left;">{{ $t('settings.inputContent') }}</div>
								<textarea class="def-input-textarea" v-model="inputValue" maxlength="160" />
							</div>
							<button class="def-add-btn" @click="addRow">
								<svg width="28" height="28" viewBox="0 0 28 28">
									<circle cx="14" cy="14" r="14" fill="#2176b8" />
									<path d="M14 8v12M8 14h12" stroke="#fff" stroke-width="2" stroke-linecap="round" />
								</svg>
							</button>
						</div>
						<table class="def-table">
							<thead>
								<tr>
									<th
										style="width: 80px;border-right: 1px solid #fff;text-align: center;border-radius: 20px 0px 0px 0;">
										{{ $t('report.serialNumber') }}</th>
									<th style="border-right: 1px solid #fff;text-align: center;">{{ $t('settings.content') }}</th>
									<th style="width: 160px;text-align: center;border-radius: 0 20px 0px 0;">{{ $t('settings.operation')
									}}</th>
								</tr>
							</thead>
							<tbody>
								<tr v-for="(row, idx) in tableData" :key="row.id">
									<td class="def-td-serial">
										<div style="width: 120px;text-align: center;">{{ idx + 1 }}</div>
									</td>
									<!-- @click="startEdit(idx)" -->
									<td class="def-td-content">
										<div >{{ row.advice }}</div>
										<!-- <input v-else v-model="editingValue" class="edit-input" @blur="confirmEdit(idx)" /> -->
									</td>
									<td class="def-td-actions">
										<button @click="checkedRow(idx)" class="def-circle-btn checked" title="勾选">
											<i class="iconfont icon-duigou"></i>
										</button>
										<button @click="saveEdit(idx)" class="def-circle-btn edit" title="编辑">
											<i class="iconfont icon-xiugai"></i>
										</button>
										<button @click="deleteRow(idx)" class="def-circle-btn " title="删除">
											<i class="iconfont icon-shanchu"></i>
										</button>
									</td>
								</tr>
							</tbody>
						</table>
					</div>
				</div>
			</Dialog>
			<Message ref="messageRef" />
			<Dialog ref="dialogRef" >
      <div>
        <div style="color: #000;font-size: 22px;margin-top: 20px;">
        {{ $t('views.report.editTip') }}
      </div>
      <div class="dialog-btn" style="margin-top: 70px;">
        <button class="dialog-confirm" @click="eidtSave">{{ $t('common.confirm') }}</button>
        <button class="dialog-cancel" @click="closeDialog">{{ $t('common.cancel') }}</button>
      </div>
      </div>
    
    </Dialog>
		<Dialog ref="emptyRef" >
      <div>
        <div style="color: #000;font-size: 22px;margin-top: 20px;">
        {{ $t('views.report.editTipSave') }}
      </div>
      <div class="dialog-btn" style="margin-top: 70px;">
        <button class="dialog-confirm" @click="closeEdit">{{ $t('common.confirm') }}</button>
        <button class="dialog-cancel" @click="emptyRef.close()">{{ $t('common.cancel') }}</button>
      </div>
      </div>
    
    </Dialog>
		
		</div>
	</div>
</template>

<script setup lang="ts">
import * as echarts from 'echarts';
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';

import html2canvas from 'html2canvas';
import Dialog from '../../components/Dialog.vue';
import Message from '../../components/Message.vue';
declare global {
	interface Window {
		electron?: {
			ipcRenderer?: {
				invoke: (channel: string, ...args: any[]) => Promise<any>
			}
		}
	}
}
const emptyRef = ref<any>(null);
const route = useRoute()
const messageRef = ref<any>(null);
const dialogRef = ref<any>(null);
// 使用备用翻译系统
let t = (key: any, params?: any) => key
let setLang = (newLang: any) => { }

// 创建响应式的翻译函数
const translationVersion = ref(0)
const $t = (key: any) => {
	// 依赖translationVersion来触发响应式更新
	translationVersion.value
	return t(key)
}
let tempIndex = -1
const eidtSave = () => {
	dialogRef.value.close()
	saveEdit(tempIndex)
	tempIndex = -1

}
const closeEdit = () => {
	console.log(1);
	
	emptyRef.value.close2()
	orderRef.value.close2()
}
const closeEmpty = () => {
	console.log(inputValue.value);
	
	if(inputValue.value){
		emptyRef.value.open()
	} else {
		inputValue.value=''
		
		orderRef.value.close2()
	}
}

// 初始化翻译函数
const initTranslations = async () => {
	try {
		const fallback = await import('../../utils/i18n-fallback')
		t = fallback.t
		setLang = (newLang: any) => {
			fallback.setLang(newLang)
			translationVersion.value++
		}
		// 监听语言变化事件
		window.addEventListener('language-changed', () => {
			translationVersion.value++
		})
	} catch (error) {
		console.warn('Failed to load i18n fallback:', error)
	}
}
const orderRef = ref<any>(null);
const router = useRouter();
const timeChartRef = ref<HTMLDivElement | null>(null);
const resultChartRef = ref<HTMLDivElement | null>(null);
let timeChart: echarts.ECharts | null = null;
let resultChart: echarts.ECharts | null = null;

// 错误处理
const hasError = ref(false);
const errorMessage = ref('');

const resultData = [14, 5, 0];
const notSave = () => {
	orderRef.value.close()
}
const closeDialog = () => {
	dialogRef.value.close()
	tempIndex = -1
}
// 获取选中选项的分数显示（支持数值和字母等级）
const getSelectedScore = (options: any[]) => {
	if (!options || !options.length) return '';

	// 筛选真正选中的选项（必须有isSelected字段且为true）
	const selectedOptions = options.filter((o: any) => o.hasOwnProperty('isSelected') && o.isSelected === true);
	if (!selectedOptions.length) return '';

	// 如果只有一个选中项，直接返回其分数
	if (selectedOptions.length === 1) {
		const score = selectedOptions[0].score;
		// 对于数字类型（包括0），直接返回；其他情况检查是否有值
		if (typeof score === 'number') {
			return score.toString();
		}
		return score !== undefined && score !== null && score !== '' ? score : '';
	}

	// 多个选中项的情况
	const scores = selectedOptions.map((o: any) => o.score);

	// 检查是否都是数值（包括0）
	const allNumbers = scores.every((score: any) => {
		return typeof score === 'number' || (!isNaN(Number(score)) && score !== '' && score !== null && score !== undefined);
	});

	if (allNumbers) {
		// 如果都是数值，进行累加
		return scores.reduce((sum: number, score: any) => sum + Number(score), 0);
	} else {
		// 如果包含字母等级，用逗号连接（过滤掉空值）
		return scores.filter((score: any) => score !== '' && score !== null && score !== undefined).join(', ');
	}
}

// 计算一级大题总分（支持三级结构）
const getTypeScore = (type: any) => {
	if (!type.questionList || !type.questionList.length) {
		// 如果没有子题，显示大题本身的分数
		return getSelectedScore(type.options) || type.score || '';
	}

	// 有子题的情况，计算所有子题的数值分数总和
	let total = 0;
	let hasNumericScore = false;

	type.questionList.forEach((question: any) => {
		// 如果有第三级子题
		if (question.questionList && question.questionList.length > 0) {
			question.questionList.forEach((subQuestion: any) => {
				if (subQuestion.options && subQuestion.options.length > 0) {
					const selectedOptions = subQuestion.options.filter((option: any) => option.isSelected);
					selectedOptions.forEach((option: any) => {
						const score = Number(option.score);
						if (!isNaN(score)) {
							total += score;
							hasNumericScore = true;
						}
					});
				}
			});
		} else if (question.options && question.options.length > 0) {
			// 没有第三级子题的情况
			const selectedOptions = question.options.filter((option: any) => option.isSelected);
			selectedOptions.forEach((option: any) => {
				const score = Number(option.score);
				if (!isNaN(score)) {
					total += score;
					hasNumericScore = true;
				}
			});
		}
	});

	return hasNumericScore ? total : '';
}

// 计算二级题目总分（有第三级子题的情况）
const getSubTypeScore = (item: any) => {
	if (!item.questionList || !item.questionList.length) {
		return getSelectedScore(item.options) || item.score || '';
	}

	let total = 0;
	let hasNumericScore = false;

	item.questionList.forEach((subItem: any) => {
		if (subItem.options && subItem.options.length > 0) {
			const selectedOptions = subItem.options.filter((option: any) => option.isSelected);
			selectedOptions.forEach((option: any) => {
				const score = Number(option.score);
				if (!isNaN(score)) {
					total += score;
					hasNumericScore = true;
				}
			});
		}
	});

	return hasNumericScore ? total : '';
}

// 计算图表数据
const getChartData = () => {
	if (!infoData.value?.questionTypeList) return { categories: [], scores: [] }
	console.log(infoData.value);

	// 判断是否为障碍类型分析
	// TODO 这里中英文要修改
	if (infoData.value.gameName === '功能独立性评定量表') {
		return getDisabilityTypeChartData()
	}
	
	// 判断是否为功能综合评定量表(FCA)
	if (infoData.value.gameName === '功能综合评定量表(FCA)') {
		return getFCAChartData()
	}
	const categories: string[] = []
	const scores: number[] = []

	infoData.value.questionTypeList.forEach((type: any) => {
		categories.push(type.questionType || type.title || '未知')

		let totalScore = 0
		if (type.questionList && type.questionList.length > 0) {
			type.questionList.forEach((question: any) => {
				// 如果有第三级子题
				if (question.questionList && question.questionList.length > 0) {
					question.questionList.forEach((subQuestion: any) => {
						if (subQuestion.options && subQuestion.options.length > 0) {
							// 只累加数值类型的分数
							const selectedOptions = subQuestion.options.filter((option: any) => option.isSelected)
							selectedOptions.forEach((option: any) => {
								const score = Number(option.score)
								if (!isNaN(score)) {
									totalScore += score
								}
							})
						}
					})
				} else if (question.options && question.options.length > 0) {
					// 没有第三级子题的情况
					const selectedOptions = question.options.filter((option: any) => option.isSelected)
					selectedOptions.forEach((option: any) => {
						const score = Number(option.score)
						if (!isNaN(score)) {
							totalScore += score
						}
					})
				}
			})
		} else if (type.options && type.options.length > 0) {
			// 处理大题本身有选项的情况
			const selectedOptions = type.options.filter((option: any) => option.isSelected)
			selectedOptions.forEach((option: any) => {
				const score = Number(option.score)
				if (!isNaN(score)) {
					totalScore += score
				}
			})
		}
		scores.push(totalScore)
	})

	return { categories, scores }
}

// 功能综合评定量表(FCA)的图表数据计算
const getFCAChartData = () => {
	const categories = [
		'自我照料',
		'括约肌控制',
		'转移',
		'行走',
		'言语理解',
		'言语表达',
		'社会交往（住院患者）',
		'社会交往（门诊或出院患者）',
		'问题解决能力',
		'记忆能力'
	]
	const scores = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

	// 遍历所有题目，根据题目标题精确分类
	infoData.value.questionTypeList.forEach((type: any) => {
		if (type.questionList && type.questionList.length > 0) {
			type.questionList.forEach((question: any) => {
				let categoryIndex = -1

				// 如果有第三级子题，遍历子题
				if (question.questionList && question.questionList.length > 0) {
					// 根据二级题目标题判断分类
					const title = question.title || ''
					
					if (title.includes('言语理解')) {
						categoryIndex = 4 // 言语理解
					} else if (title.includes('言语表达')) {
						categoryIndex = 5 // 言语表达
					} else if (title.includes('社会交往（住院患者）')) {
						categoryIndex = 6 // 社会交往（住院患者）
					} else if (title.includes('社会交往（门诊或出院患者）')) {
						categoryIndex = 7 // 社会交往（门诊或出院患者）
					} else if (title.includes('问题解决')) {
						categoryIndex = 8 // 问题解决能力
					} else if (title.includes('记忆')) {
						categoryIndex = 9 // 记忆能力
					}

					// 累加三级子题的分数
					if (categoryIndex !== -1) {
						question.questionList.forEach((subQuestion: any) => {
							if (subQuestion.options && subQuestion.options.length > 0) {
								const selectedOptions = subQuestion.options.filter((option: any) => option.hasOwnProperty('isSelected') && option.isSelected === true)
								selectedOptions.forEach((option: any) => {
									const score = Number(option.score)
									if (!isNaN(score)) {
										scores[categoryIndex] += score
									}
								})
							}
						})
					}
				} else {
					// 没有子题的情况，直接处理该题目
					const title = question.title || ''
					
					// 运动功能分类
					if (title.includes('自我照料')) {
						categoryIndex = 0 // 自我照料
					} else if (title.includes('括约肌控制') || title.includes('排尿') || title.includes('排便')) {
						categoryIndex = 1 // 括约肌控制
					} else if (title.includes('转移') || title.includes('床→椅') || title.includes('坐厕→轮椅') || title.includes('浴盆') || title.includes('淋浴')) {
						categoryIndex = 2 // 转移
					} else if (title.includes('行走') || title.includes('轮椅') || title.includes('楼梯')) {
						categoryIndex = 3 // 行走
					}

					// 累加该题目的分数
					if (categoryIndex !== -1 && question.options && question.options.length > 0) {
						const selectedOptions = question.options.filter((option: any) => option.hasOwnProperty('isSelected') && option.isSelected === true)
						selectedOptions.forEach((option: any) => {
							const score = Number(option.score)
							if (!isNaN(score)) {
								scores[categoryIndex] += score
							}
						})
					}
				}
			})
		}
	})

	// 保留一位小数
	const formattedScores = scores.map(score => Number(score.toFixed(1)))
	
	return { categories, scores: formattedScores }
}

// 障碍类型分析的图表数据计算
const getDisabilityTypeChartData = () => {
	const categories = [
		t('report.selfCare'),
		t('report.sphincterControl'),
		t('report.transfer'),
		t('report.walking'),
		t('report.communication'),
		t('report.socialCognition')
	]
	const scores = [0, 0, 0, 0, 0, 0]

	// 关键词映射
	const keywordMap: Record<string, number> = {
		'自理能力': 0,
		'进食': 0,
		'梳洗': 0,
		'洗澡': 0,
		'穿上衣': 0,
		'穿下衣': 0,
		'上厕所': 0,
		'括约肌': 1,
		'膀胱': 1,
		'直肠': 1,
		'转移': 2,
		'床': 2,
		'椅': 2,
		'轮椅': 2,
		'入厕': 2,
		'盆浴': 2,
		'淋浴': 2,
		'行走': 3,
		'步行': 3,
		'楼梯': 3,
		'交流': 4,
		'理解': 4,
		'表达': 4,
		'社会认知': 5,
		'社会交往': 5,
		'解决问题': 5,
		'记忆': 5
	}

	// 遍历所有题目，根据标题关键词分类累加分数
	infoData.value.questionTypeList.forEach((type: any) => {
		if (type.questionList && type.questionList.length > 0) {
			type.questionList.forEach((question: any) => {
				if (question.title && question.options && question.options.length > 0) {
					// 查找匹配的关键词
					let categoryIndex = -1
					for (const [keyword, index] of Object.entries(keywordMap)) {
						if (question.title.includes(keyword)) {
							categoryIndex = index
							break
						}
					}

					// 如果找到匹配的分类，累加选中选项的分数
					if (categoryIndex !== -1) {
						const selectedOptions = question.options.filter((option: any) => option.isSelected)
						selectedOptions.forEach((option: any) => {
							const score = Number(option.score)
							if (!isNaN(score)) {
								scores[categoryIndex] += score
							}
						})
					}
				}
			})
		}
	})

	return { categories, scores }
}

const tableScale = ref(1);
const hasShownZoomTip = ref(false);

// 监听缩放值变化，更新滚动条样式
watch(tableScale, (newScale) => {
	if (reportMainRef.value) {
		if (newScale > 1) {
			reportMainRef.value.classList.add('scaled');
			// 缩放后稍微滚动一下，确保滚动条可见
			setTimeout(() => {
				if (reportMainRef.value) {
					reportMainRef.value.scrollTop = 1;
					reportMainRef.value.scrollTop = 0;
				}
			}, 100);
			
			// 第一次缩放时显示提示
			if (!hasShownZoomTip.value) {
				hasShownZoomTip.value = true;
				if (messageRef.value) {
					messageRef.value.show('缩放后可以滚动查看完整内容', 'info');
				}
			}
		} else {
			reportMainRef.value.classList.remove('scaled');
		}
	}
});

const exitReport = async () => {
	try {
		// 先保存报告（不显示消息提示）
	} catch (error) {
		console.warn('退出时保存失败:', error)
	}

	// 然后退出页面
	if (route.query.id) {
		router.back();

	} else {
		await savePdf(false)
		router.go(-2)
	}
}
const setDefault = () => {
	orderRef.value.open();
}

const infoData = ref<any>({})

const inputValue = ref('')
const tableData = ref<any[]>([])
const editingIndex = ref<number>(-1)
const editingValue = ref('')

// 鼠标拖拽滚动相关
const isDragging = ref(false)
const startY = ref(0)
const startX = ref(0)
const startScrollTop = ref(0)
const startScrollLeft = ref(0)
const reportMainRef = ref<HTMLElement | null>(null)

// 音频播放相关
const currentPlaying = ref<string>('')
const isLoading = ref<Record<string, boolean>>({})
let currentAudio: HTMLAudioElement | null = null

const toggleAudio = (audioUrl: string, audioId: string) => {
	if (currentPlaying.value === audioId) {
		// 暂停当前播放
		if (currentAudio) {
			currentAudio.pause()
			currentAudio = null
		}
		currentPlaying.value = ''
	} else {
		// 停止之前的播放
		if (currentAudio) {
			currentAudio.pause()
			currentAudio = null
		}

		// 开始新的播放
		isLoading.value[audioId] = true
		currentAudio = new Audio(audioUrl)

		currentAudio.addEventListener('loadeddata', () => {
			isLoading.value[audioId] = false
			currentPlaying.value = audioId
		})

		currentAudio.addEventListener('ended', () => {
			currentPlaying.value = ''
			currentAudio = null
		})

		currentAudio.addEventListener('error', () => {
			isLoading.value[audioId] = false
			currentPlaying.value = ''
			currentAudio = null
			messageRef.value?.show(t('report.audioError'), 'error')
		})

		currentAudio.play().catch(() => {
			isLoading.value[audioId] = false
			currentPlaying.value = ''
			currentAudio = null
			messageRef.value?.show(t('report.audioError'), 'error')
		})
	}
}
const addRow = () => {
	if (!inputValue.value.trim()) {
		messageRef.value.show(t('messages.pleaseInput'), 'error')
		return
	}
	if (editingIndex.value != -1) {
		confirmEdit(editingIndex.value)
	} else { 
		window.request?.('/system/advice', {
		method: 'POST',
		body: {
			advice: inputValue.value.trim(),
		}
	}).then(res => {
		if (res?.data) {
			tableData.value.push(res.data)
		}
		getAdviceList()

		inputValue.value = ''
	})
	}
	
}
const deleteRow = (idx: number) => {
	const id = tableData.value[idx]?.id
	if (id) {
		window.request?.(`/system/advice/${id}`, { method: 'DELETE' }).then(() => {
			tableData.value.splice(idx, 1)
		})
		getAdviceList()

	}
}
const checkedRow = (idx: number) => {
	const val = tableData.value[idx]?.advice || ''
	assessAdvice.value = val
	orderRef.value.close2()
}
const startEdit = (idx: number) => {
	editingIndex.value = idx
	editingValue.value = tableData.value[idx]?.advice || ''
}
const cancelEdit = () => {
	editingIndex.value = -1
}
const confirmEdit = (idx: number) => {
	// const id = tableData.value[idx]?.id
	window.request?.(`/system/advice`, {
			method: 'PUT',
			body: {
				id: tableData.value[idx]?.id,
				advice: inputValue.value.trim()
			}
		}).then(res => {
			messageRef.value?.show(t('report.saveSuccess'), 'success')
			getAdviceList()
			if (res?.data) {
				tableData.value[idx] = res.data
			}
		})
	editingIndex.value = -1
}
const saveEdit = (idx: number) => {
	console.log(tempIndex);
	
	if (inputValue.value&&tempIndex==-1) {
		dialogRef.value.open()
		tempIndex = idx
		return
	 }
	editingIndex.value = idx
	inputValue.value = tableData.value[idx]?.advice || ''
}
const getAdviceList = () => {
	window.request?.('/system/advice/list', {
		method: 'GET', params: {
			pageSize: 9999,
		}
	}).then(res => {
		console.log(res);

		tableData.value = Array.isArray(res?.rows) ? res.rows : []
	})
}
const formatTime = (time: number | string, fmt: string = 'yyyy-MM-dd HH:mm:ss') => {
	let date: Date
	if (typeof time === 'string' && /^\d+$/.test(time)) {
		date = new Date(Number(time))
	} else if (typeof time === 'number') {
		date = new Date(time)
	} else {
		date = new Date(time as string)
	}
	const pad = (n: number) => n < 10 ? '0' + n : n.toString()
	const map: Record<string, string> = {
		'yyyy': date.getFullYear().toString(),
		'MM': pad(date.getMonth() + 1),
		'dd': pad(date.getDate()),
		'HH': pad(date.getHours()),
		'mm': pad(date.getMinutes()),
		'ss': pad(date.getSeconds()),
	}
	return fmt
		.replace('yyyy', map['yyyy'])
		.replace('MM', map['MM'])
		.replace('dd', map['dd'])
		.replace('HH', map['HH'])
		.replace('mm', map['mm'])
		.replace('ss', map['ss'])
}
const initCharts = () => {
	try {
		if (!infoData.value?.horizontalAxis?.length) {
			console.log('No chart data available');
			return;
		}

		if (timeChartRef.value) {
			// 销毁现有图表
			if (timeChart) {
				try {
					timeChart.dispose();
				} catch (e) {
					console.warn('Error disposing previous chart:', e);
				}
				timeChart = null;
			}

			try {
				timeChart = echarts.init(timeChartRef.value);
				if (!timeChart) {
					console.error('Failed to create chart instance');
					return;
				}

				const chartData = getChartData();


				const dataLength = infoData.value.horizontalAxis.length;

				timeChart.setOption({
					grid: {
						left: 50,
						right: 30,
						top: 40,
						bottom: dataLength > 5 ? 80 : 60
					},
					xAxis: {
						type: 'category',
						data: infoData.value.horizontalAxis || [],
						axisLine: { lineStyle: { color: '#2176b8' } },
						axisLabel: {
							color: '#2176b8',
							fontWeight: 500,
							rotate: dataLength > 9 ? 19 : 0,
							interval: 0,
							fontSize: 12,
							margin: 8
						},
						axisTick: {
							alignWithLabel: true
						}
					},
					yAxis: {
						type: 'value',
						name: t('report.unit'),
						nameTextStyle: { color: '#2176b8', fontWeight: 500, fontSize: 13 },
						axisLine: { lineStyle: { color: '#2176b8' } },
						axisLabel: { color: '#2176b8', fontWeight: 500 },
						splitLine: { lineStyle: { color: '#e0eaf3' } },
					},
					series: [{
						data: chartData.scores || [],
						type: 'bar',
						itemStyle: {
							color: function (params: any) {
								const colors = ['#2176b8', '#4caf50', '#ff9800', '#e91e63', '#9c27b0', '#00bcd4', '#ffeb3b', '#795548', '#607d8b', '#f44336'];
								return colors[params.dataIndex % colors.length];
							},
							borderRadius: [6, 6, 0, 0],
						},
						barWidth: Math.min(40, Math.max(20, 300 / Math.max(dataLength, 1))),
						label: {
							show: true,
							position: 'top',
							color: '#2176b8',
							fontSize: 13,
							fontWeight: 500,
						},
					}],
					tooltip: {
						trigger: 'axis',
						backgroundColor: 'rgba(255, 255, 255, 0.95)',
						borderColor: '#2176b8',
						borderWidth: 1,
						textStyle: {
							color: '#333'
						},
						formatter: function (params: any) {
							if (!params || !params[0]) return '';
							const data = params[0];
							return `${data.name}<br/>${t('common.score')}: ${parseFloat(data.value).toFixed(1)}${t('common.score')}`;
						}
					}
				});

				console.log('Chart initialized successfully');
			} catch (chartError) {
				console.error('Chart creation error:', chartError);
				// 图表创建失败时不抛出错误，只是跳过图表
			}
		}

		// 简化第二个图表的初始化，如果有需要的话
		if (resultChartRef.value && resultData && resultData.length > 0) {
			try {
				if (resultChart) {
					resultChart.dispose();
					resultChart = null;
				}

				resultChart = echarts.init(resultChartRef.value);
				if (resultChart) {
					resultChart.setOption({
						grid: { left: 40, right: 20, top: 30, bottom: 30 },
						xAxis: {
							type: 'category',
							data: [t('report.correct'), t('report.incorrect'), t('report.hint')],
							axisLine: { lineStyle: { color: '#2176b8' } },
							axisLabel: { color: '#2176b8', fontWeight: 500 },
						},
						yAxis: {
							type: 'value',
							name: t('report.unitTimes'),
							nameTextStyle: { color: '#2176b8', fontWeight: 500, fontSize: 13 },
							axisLine: { lineStyle: { color: '#2176b8' } },
							axisLabel: { color: '#2176b8', fontWeight: 500 },
							splitLine: { lineStyle: { color: '#e0eaf3' } },
						},
						series: [{
							data: resultData,
							type: 'bar',
							itemStyle: {
								color: function (params: any) {
									return ['#2176b8', '#4caf50', '#bdbdbd'][params.dataIndex];
								},
								borderRadius: [6, 6, 0, 0],
							},
							barWidth: 32,
							label: {
								show: true,
								position: 'top',
								color: '#2176b8',
								fontSize: 13,
								fontWeight: 500,
							},
						}],
					});
				}
			} catch (resultChartError) {
				console.error('Result chart creation error:', resultChartError);
			}
		}
	} catch (error) {
		console.error('Charts initialization error:', error);
		// 不要让图表错误影响整个页面
	}
}
let upData: any = null
const upLoadFile = async () => {
	try {
		if (!upData || !upData.questionTypeList) {
			console.log('No data to upload');
			return;
		}

		// 收集所有需要上传的文件
		const filesToUpload: Array<{
			data: string,
			type: 'canvas' | 'audio',
			path: string
		}> = [];

		// 安全地遍历questionTypeList
		if (Array.isArray(upData.questionTypeList)) {
			upData.questionTypeList.forEach((type: any, typeIdx: number) => {
				try {
					// 检查大题级别的audio
					if (type.audio && typeof type.audio === 'string') {
						filesToUpload.push({
							data: type.audio,
							type: 'audio',
							path: `questionTypeList[${typeIdx}].audio`
						});
					}

					// 检查子题
					if (type.questionList && Array.isArray(type.questionList)) {
						type.questionList.forEach((question: any, questionIdx: number) => {
							try {
								// 检查canvas
								if (question.canvas && typeof question.canvas === 'string') {
									filesToUpload.push({
										data: question.canvas,
										type: 'canvas',
										path: `questionTypeList[${typeIdx}].questionList[${questionIdx}].canvas`
									});
								}
								// 检查audio
								if (question.audio && typeof question.audio === 'string') {
									filesToUpload.push({
										data: question.audio,
										type: 'audio',
										path: `questionTypeList[${typeIdx}].questionList[${questionIdx}].audio`
									});
								}
							} catch (questionError) {
								console.warn(`Error processing question ${typeIdx}-${questionIdx}:`, questionError);
							}
						});
					}
				} catch (typeError) {
					console.warn(`Error processing type ${typeIdx}:`, typeError);
				}
			});
		}

		console.log(`Found ${filesToUpload.length} files to upload`);

		// 逐个上传文件
		for (const file of filesToUpload) {
			try {
				if (!window.request) {
					console.warn('Upload function not available');
					break;
				}

				let formData = new FormData();

				if (file.type === 'canvas') {
					// Canvas数据是base64格式，需要转换为Blob
					const base64Data = file.data.split(',')[1];
					if (!base64Data) continue;

					const byteCharacters = atob(base64Data);
					const byteNumbers = new Array(byteCharacters.length);
					for (let i = 0; i < byteCharacters.length; i++) {
						byteNumbers[i] = byteCharacters.charCodeAt(i);
					}
					const byteArray = new Uint8Array(byteNumbers);
					const blob = new Blob([byteArray], { type: 'image/png' });
					formData.append('file', blob, `canvas_${Date.now()}.png`);
				} else if (file.type === 'audio') {
					// Audio数据可能是blob URL
					if (file.data.startsWith('blob:')) {
						const response = await fetch(file.data);
						const blob = await response.blob();
						formData.append('file', blob, `audio_${Date.now()}.wav`);
					} else {
						console.warn('Unsupported audio format:', file.data);
						continue;
					}
				}

				// 上传文件
				const uploadResponse = await window.request('/common/upload', {
					method: 'POST',
					body: formData
				});

				if (uploadResponse && uploadResponse.url) {
					// 上传成功，更新数据中的URL
					const pathParts = file.path.split('.');
					let target = upData;

					// 导航到目标位置
					for (let i = 0; i < pathParts.length - 1; i++) {
						const part = pathParts[i];
						if (part.includes('[') && part.includes(']')) {
							const arrayName = part.split('[')[0];
							const index = parseInt(part.split('[')[1].split(']')[0]);
							if (target[arrayName] && target[arrayName][index]) {
								target = target[arrayName][index];
							} else {
								throw new Error(`Invalid path: ${file.path}`);
							}
						} else {
							if (target[part]) {
								target = target[part];
							} else {
								throw new Error(`Invalid path: ${file.path}`);
							}
						}
					}

					// 设置新的URL
					const finalKey = pathParts[pathParts.length - 1];
					target[finalKey] = uploadResponse.url;

					console.log(`Uploaded ${file.type} file: ${file.path} -> ${uploadResponse.url}`);
				}
			} catch (fileError) {
				console.error(`Error uploading file ${file.path}:`, fileError);
				// 继续处理其他文件
			}
		}

		// 更新infoData
		try {
			infoData.value = { ...infoData.value, ...upData };
			localStorage.setItem('infoData', JSON.stringify(infoData.value));
			console.log('File upload completed');
		} catch (updateError) {
			console.error('Error updating data after upload:', updateError);
		}

	} catch (error) {
		console.error('Error in upLoadFile:', error);
		// 不要让上传错误阻止页面渲染
	}
}

// 窗口大小变化处理函数
let handleResize: (() => void) | null = null

// 鼠标拖拽滚动事件处理
const handleMouseDown = (e: MouseEvent) => {
	// 如果点击的是按钮、输入框等交互元素，不启动拖拽
	const target = e.target as HTMLElement
	if (target.tagName === 'BUTTON' || target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' ||
		target.closest('button') || target.closest('input') || target.closest('textarea')) {
		return
	}

	if (!reportMainRef.value) return
	isDragging.value = true
	startY.value = e.clientY
	startX.value = e.clientX
	startScrollTop.value = reportMainRef.value.scrollTop
	startScrollLeft.value = reportMainRef.value.scrollLeft

	document.addEventListener('mousemove', handleMouseMove)
	document.addEventListener('mouseup', handleMouseUp)
	e.preventDefault()
}

const handleMouseMove = (e: MouseEvent) => {
	if (!isDragging.value || !reportMainRef.value) return
	const deltaY = e.clientY - startY.value
	const deltaX = e.clientX - startX.value
	reportMainRef.value.scrollTop = startScrollTop.value - deltaY
	reportMainRef.value.scrollLeft = startScrollLeft.value - deltaX
	e.preventDefault()
}

const handleMouseUp = () => {
	isDragging.value = false
	document.removeEventListener('mousemove', handleMouseMove)
	document.removeEventListener('mouseup', handleMouseUp)
}

const getData = async () => {

}

const showUnitName: any = ref(false)
const unitName: any = ref('')
const contentData: any = ref({})
onMounted(async () => {
	// 初始化翻译系统
	await initTranslations()

	// 检查初始缩放值，设置滚动条样式
	if (reportMainRef.value && tableScale.value > 1) {
		reportMainRef.value.classList.add('scaled');
	}

	//获取数据 不是新增
	if (route.query.id) {
		addId = route.query.id as string
		let data: any = await window.request?.('/system/scaleRecord/' + addId, { method: 'GET', })
		console.log(data);
		assessAdvice.value = data.assessAdvice
		therapistSignature.value = data.therapistSignature
		contentData.value = data
		const parsedContent = JSON.parse(data.content);
		const parsedScoreDetail = JSON.parse(data.scoreDetail);
		console.log('Content data:', parsedContent);
		console.log('ScoreDetail data:', parsedScoreDetail);

		try {
			console.log('Attempting to merge content and scoreDetail data...');
			// 合并content和scoreDetail数据
			infoData.value = mergeContentAndScoreDetail(parsedContent, parsedScoreDetail);
			
			// 如果解析的数据中有用户信息，则合并本地用户数据
			if (infoData.value.user) {
				const localUserStr = localStorage.getItem('user')
				if (localUserStr) {
					try {
						const localUser = JSON.parse(localUserStr)
						// 合并本地用户数据和API用户数据，优先使用本地数据
						infoData.value.user = {
							...infoData.value.user,
							...localUser,
							// 确保关键字段不被覆盖
							id: localUser.id || infoData.value.user.id,
							name: localUser.name || infoData.value.user.name,
							age: localUser.age || infoData.value.user.age,
							anamnesisid: localUser.anamnesisid || infoData.value.user.anamnesisid
						}
						console.log('Table.vue - Using merged user data:', infoData.value.user)
					} catch (parseError) {
						console.warn('Table.vue - Failed to parse local user data:', parseError)
					}
				}
			}
			
			console.log('Merged data successful, infoData:', infoData.value);
			console.log('User data:', infoData.value.user);
			console.log('Merged startTime:', infoData.value.startTime);
			console.log('Merged endTime:', infoData.value.endTime);
			console.log('Merged gameName:', infoData.value.gameName);
			console.log('User age:', infoData.value.user?.age);
			console.log('User anamnesisid:', infoData.value.user?.anamnesisid);
			console.log('Data loading completed, infoData exists:', !!infoData.value);
			console.log('User exists:', !!infoData.value?.user);
			console.log('Available keys in infoData:', Object.keys(infoData.value || {}));
			
			// 如果解析的数据中没有用户信息，从本地缓存获取
			if (!infoData.value.user) {
				console.log('No user data in parsed content, getting from localStorage...');
				const localUserStr = localStorage.getItem('user')
				if (localUserStr) {
					try {
						const localUser = JSON.parse(localUserStr)
						infoData.value.user = localUser
						console.log('User data set from localStorage:', infoData.value.user)
					} catch (parseError) {
						console.warn('Failed to parse local user data:', parseError)
					}
				} else {
					console.warn('No user data found in localStorage')
				}
			}
			
			// 如果解析的数据中没有时间信息，从API数据获取
			if (!infoData.value.startTime && data.startTime) {
				console.log('No startTime in parsed content, getting from API data...');
				infoData.value.startTime = data.startTime
			}
			if (!infoData.value.endTime && data.endTime) {
				console.log('No endTime in parsed content, getting from API data...');
				infoData.value.endTime = data.endTime
			}
			
			// 如果仍然没有时间信息，使用当前时间作为备用
			if (!infoData.value.startTime) {
				console.log('No startTime found, using current time...');
				infoData.value.startTime = Date.now()
			}
			if (!infoData.value.endTime) {
				console.log('No endTime found, using current time...');
				infoData.value.endTime = Date.now()
			}
			
			// 如果解析的数据中没有gameName，从API数据获取
			if (!infoData.value.gameName && data.scaleName) {
				console.log('No gameName in parsed content, getting from API data...');
				infoData.value.gameName = data.scaleName
			}
			
			console.log('Final infoData startTime:', infoData.value.startTime);
			console.log('Final infoData endTime:', infoData.value.endTime);
			console.log('Final infoData gameName:', infoData.value.gameName);
		} catch (parseError) {
			console.error('JSON parse error:', parseError);
			console.error('Raw data:', data.content);


		}
	}
	try {
		// 安全地获取配置数据
		try {
			showUnitName.value = localStorage.getItem('showUnitName') === 'true';
			unitName.value = localStorage.getItem('unitName') || '';
		} catch (configError) {
			console.warn('Config loading error:', configError);
		}


		console.log(infoData.value);


		// 创建数据副本用于上传
		if (!route.query.id) {
			try {
				// 安全地初始化数据
				if (!safeDataInit()) {
					return; // 如果数据初始化失败，不继续执行
				}
				upData = JSON.parse(JSON.stringify(infoData.value));
			} catch (copyError) {
				console.warn('Data copy error:', copyError);
				upData = infoData.value; // 使用原始数据
			}
		}
		//结束任务
		if (localStorage.getItem('taskId')) {

			let user = JSON.parse(localStorage.getItem('user') || '{}')
			let taskId: any = localStorage.getItem('taskId')
			if (!taskId) {
				taskId = {
					id: ''
				}
			} else {
				taskId = JSON.parse(taskId)
			}
			let resource = localStorage.getItem('resource')
			//开始任务
			// window.request?.('/task/actionTask', {
			// 	method: 'POST', body: {
			// 		id: localStorage.getItem('scaleId'),
			// 		taskId: taskId.id,
			// 		executionNumber: taskId.executionNumber,
			// 		patientId: user.id,
			// 		resource: resource,
			// 		action: 3,
			// 		linkName: infoData.value.gameName,
			// 		linkId: localStorage.getItem('scaleId'),
			// 		type: 2
			// 	}
			// })

		}

		// 判断是否显示分数
		try {
			if (infoData.value.questionTypeList && Array.isArray(infoData.value.questionTypeList)) {
				infoData.value.questionTypeList.forEach((item: any) => {
					if (item.questionList && Array.isArray(item.questionList)) {
						item.questionList.forEach((question: any) => {
							if (question.options && Array.isArray(question.options)) {
								question.options.forEach((option: any) => {
									if (option.score && isNaN(option.score)) {
										showScore.value = false;
									}
								});
							}
						});
					}
				});
			}
		} catch (scoreError) {
			console.warn('Score checking error:', scoreError);
		}

		// 安全地上传文件
		try {
			await upLoadFile();
		} catch (uploadError) {
			console.warn('File upload error:', uploadError);
			// 继续执行，不让上传错误阻止页面渲染
		}

		// 获取评测预设列表
		try {
			getAdviceList();
		} catch (adviceError) {
			console.warn('Advice list error:', adviceError);
		}

		// 延迟初始化图表
		setTimeout(() => {
			try {
				initCharts();
			} catch (chartError) {
				console.warn('Chart initialization error:', chartError);
			}
		}, 200);

		// 添加窗口大小变化监听
		handleResize = () => {
			try {
				if (timeChart) {
					timeChart.resize();
				}
				if (resultChart) {
					resultChart.resize();
				}
			} catch (resizeError) {
				console.warn('Chart resize error:', resizeError);
			}
		}
		window.addEventListener('resize', handleResize);

	} catch (error) {
		handleError(error, '页面初始化');
	}

});

onBeforeUnmount(() => {
	// 移除窗口大小变化监听器
	if (handleResize) {
		window.removeEventListener('resize', handleResize)
		handleResize = null
	}

	// 销毁图表实例
	if (timeChart) {
		timeChart.dispose();
		timeChart = null;
	}
	if (resultChart) {
		resultChart.dispose();
		resultChart = null;
	}
	// 清理音频资源
	if (currentAudio) {
		currentAudio.pause();
		currentAudio = null;
	}
});
let addId = ''
const assessAdvice = ref('')
const therapistSignature = ref('')
let isAdd = false

const addHisData = (imageBase64: string) => {
	let taskId: any = localStorage.getItem('taskId')
	// console.log();
	// 	let a = JSON.stringify(infoData.value)
	// 	let b = JSON.parse(a)
	// 	console.log(a);

	// 	console.log(b);

	if (!taskId) {
		taskId = {
			id: ''
		}
	} else {
		taskId = JSON.parse(taskId)
	}
	let obj: any = {
		image: imageBase64,
		scaleName: infoData.value.gameName,
		assessAdvice: assessAdvice.value,
		isTempSave: 1,
		patientId: infoData.value.user.id,
		scaleId: localStorage.getItem('scaleId'),
		therapistSignature: therapistSignature.value,
		total: getTotalScore(),
		taskId: taskId.id,
		executionNumber: taskId.executionNumber,
		// TODO 这里的任务还没传
		content: JSON.stringify(infoData.value),
		scoreDetail: JSON.stringify(infoData.value),
		patientName: infoData.value.user.name,
		startTime: formatTime(infoData.value.startTime, 'yyyy-MM-dd HH:mm:ss'),
		endTime: formatTime(infoData.value.endTime, 'yyyy-MM-dd HH:mm:ss'),
	}
	isAdd = true
	//修改
	if (addId) {
		obj.id = addId
		window.request?.('/system/scaleRecord', { method: 'PUT', body: obj }).then((res: any) => {
			console.log(res);
			if (res.id) {
				addId = res.id
			 }
		})
	} else { 
		console.log(obj);
	//添加				
	window.request?.('/system/scaleRecord', { method: 'POST', body: obj }).then((res: any) => {
		console.log(res);
		addId = res
	})
	}


}
const savePdf = async (showMessage: boolean = true) => {
	//保存过，又退出的情况
	if (isAdd && !showMessage) { return }
	if (!reportMainRef.value) return;

	try {
		// 先获取图表的图片数据
		let chartImageData: string | null = null;
		if (timeChart && timeChartRef.value) {
			try {
				timeChart.resize();
				await new Promise(resolve => setTimeout(resolve, 200));

				chartImageData = timeChart.getDataURL({
					type: 'png',
					pixelRatio: 2,
					backgroundColor: '#fff'
				});
				console.log('Chart image data obtained');
			} catch (chartError) {
				console.error('Failed to get chart image:', chartError);
			}
		}

		// 创建离屏容器
		const offscreenContainer = document.createElement('div');
		offscreenContainer.style.position = 'absolute';
		offscreenContainer.style.top = '-99999px';
		offscreenContainer.style.left = '-99999px';
		offscreenContainer.style.width = '800px'; // 固定宽度
		offscreenContainer.style.height = 'auto';
		offscreenContainer.style.overflow = 'visible';
		offscreenContainer.style.background = '#fff';
		offscreenContainer.style.zIndex = '-9999';
		offscreenContainer.style.pointerEvents = 'none';

		// 克隆报告内容
		const reportContent = reportMainRef.value.querySelector('.report-content') as HTMLElement;
		const clonedContent = reportContent.cloneNode(true) as HTMLElement;

		// 设置克隆内容的样式
		clonedContent.style.width = '800px';
		clonedContent.style.height = 'auto';
		clonedContent.style.overflow = 'visible';
		clonedContent.style.transform = 'none';
		clonedContent.style.transformOrigin = 'unset';

		// 将克隆内容添加到离屏容器
		offscreenContainer.appendChild(clonedContent);

		// 将离屏容器添加到body
		document.body.appendChild(offscreenContainer);

		// 等待DOM更新
		await new Promise(resolve => setTimeout(resolve, 100));

		// 处理图表 - 在克隆的内容中查找图表容器
		if (chartImageData) {
			const clonedChartContainer = clonedContent.querySelector('.echart-box') as HTMLElement;
			if (clonedChartContainer) {
				clonedChartContainer.innerHTML = '';
				const chartImg = document.createElement('img');
				chartImg.src = chartImageData;
				chartImg.style.width = '100%';
				chartImg.style.height = '300px'; // 固定高度
				chartImg.style.objectFit = 'contain';
				chartImg.style.display = 'block';
				clonedChartContainer.appendChild(chartImg);

				// 等待图片加载
				await new Promise(resolve => {
					chartImg.onload = resolve;
					chartImg.onerror = resolve;
					setTimeout(resolve, 500);
				});
				console.log('Chart image added to cloned content');
			}
		}

		// 再次等待确保所有内容都准备好
		await new Promise(resolve => setTimeout(resolve, 200));

		// 获取实际尺寸
		const finalWidth = Math.max(clonedContent.scrollWidth, 800);
		const finalHeight = clonedContent.scrollHeight;

		console.log('Final dimensions:', { width: finalWidth, height: finalHeight });

		// 截图离屏内容
		const canvas = await html2canvas(clonedContent, {
			useCORS: true,
			allowTaint: true,
			scale: 2,
			scrollX: 0,
			scrollY: 0,
			width: finalWidth,
			height: finalHeight,
			backgroundColor: '#fff',
			logging: false
		});

		// 清理离屏容器
		document.body.removeChild(offscreenContainer);

		// 生成文件名
		const timestamp = formatTime(infoData.value.startTime, 'yyyyMMdd_HHmmss');
		const fileName = `${infoData.value.gameName}_${timestamp}.png`;
		const userFolderName = `${infoData.value.user.name}-${infoData.value.user.id}`;

		// 转换为blob并保存
		canvas.toBlob(async (blob: Blob | null) => {
			if (!blob) return;

			const arrayBuffer = await blob.arrayBuffer();
			await window.electron?.ipcRenderer?.invoke('save-image', fileName, arrayBuffer, userFolderName);
		}, 'image/png');


		addHisData(canvas.toDataURL('image/png'))
		if (window.messageRef?.show && showMessage) {
			window.messageRef.show(t('report.saveSuccess'), 'success');
		}
	} catch (error) {
		console.error('保存图片失败:', error);

		if (window.messageRef?.show) {
			window.messageRef.show(t('report.saveFailed'), 'error');
		}
	}
};

const showScore = ref(true)

// 检查是否有canvas数据
const hasCanvasData = computed(() => {
	if (!infoData.value?.questionTypeList) return false
	
	return infoData.value.questionTypeList.some((type: any) => {
		if (!type.questionList) return false
		
		return type.questionList.some((item: any) => {
			// 检查二级题目的canvas
			if (item.canvas) return true
			
			// 检查三级子题的canvas
			if (item.questionList && item.questionList.length > 0) {
				return item.questionList.some((subItem: any) => subItem.canvas)
			}
			
			return false
		})
	})
})
const printReport = async () => {
	try {
		// 滚动到顶部
		if (reportMainRef.value) {
			reportMainRef.value.scrollTop = 0;
		}

		// 检查是否在 Electron 环境中
		if (window.electron && window.electron.ipcRenderer) {
			// 使用 Electron 原生打印
			await printWithElectron();
		} else {
			// 使用浏览器打印
			await printWithBrowser();
		}
	} catch (error) {
		console.error('打印报告失败:', error);
		// 确保清理样式类
		document.body.classList.remove('pdf-exporting');

		// 显示错误信息
		if (messageRef.value) {
			messageRef.value.show(t('report.printFailed'), 'error');
		}
	}
};

// Electron 原生打印
const printWithElectron = async () => {
	try {
		// 添加打印样式
		document.body.classList.add('pdf-exporting');
		await new Promise(r => setTimeout(r, 300));

		let result;
		try {
			// 调用 Electron 主进程的打印功能
			result = await window.electron?.ipcRenderer?.invoke('print-report', {
				silent: false,
				printBackground: true,
				color: true,
				margins: {
					marginType: 'printableArea'
				},
				pageSize: 'A4',
				landscape: false
			});

			console.log('Electron 打印结果:', result);
		} catch (invokeError) {
			console.warn('Electron invoke 失败:', invokeError);
			// 如果 invoke 失败，降级到浏览器打印
			throw new Error('Electron 打印不可用，降级到浏览器打印');
		}

		// 检查结果是否有效
		if (!result) {
			console.warn('Electron 打印返回空结果，可能主进程未实现 print-report 处理程序');
			throw new Error('Electron 打印服务不可用');
		}

		if (result.success) {
			if (messageRef.value) {
				messageRef.value.show(t('report.printSuccess'), 'success');
			}
		} else {
			throw new Error(result.error || 'Electron print failed');
		}

	} catch (error: any) {
		console.log('Electron 打印失败，降级到浏览器打印:', error.message);
		document.body.classList.remove('pdf-exporting');
		// 降级到浏览器打印
		await printWithBrowser();
	} finally {
		document.body.classList.remove('pdf-exporting');
	}
};

// 浏览器打印
const printWithBrowser = async () => {
	try {
		// 添加打印样式类
		document.body.classList.add('pdf-exporting');

		// 等待样式应用和重新布局
		await new Promise(r => setTimeout(r, 800));

		// 直接使用当前窗口打印，避免弹窗问题
		try {
			window.print();

			// 显示成功消息
			setTimeout(() => {
				if (messageRef.value) {
					messageRef.value.show(t('report.printInitiated'), 'success');
				}
			}, 1000);

		} catch (printError) {
			console.error('直接打印失败:', printError);
			// 如果直接打印失败，尝试创建iframe方式
			await printWithIframe();
		}

	} finally {
		// 延迟移除样式类，确保打印对话框能正常显示
		setTimeout(() => {
			document.body.classList.remove('pdf-exporting');
		}, 1000);
	}
};

// 使用iframe打印（避免弹窗限制）
const printWithIframe = async () => {
	try {
		// 获取要打印的内容
		const reportContent = reportMainRef.value?.querySelector('.report-content');
		if (!reportContent) {
			throw new Error('找不到报告内容');
		}

		// 创建隐藏的iframe
		const iframe = document.createElement('iframe');
		iframe.style.position = 'absolute';
		iframe.style.top = '-9999px';
		iframe.style.left = '-9999px';
		iframe.style.width = '0px';
		iframe.style.height = '0px';
		iframe.style.border = 'none';

		document.body.appendChild(iframe);

		// 等待iframe加载
		await new Promise<void>((resolve) => {
			iframe.onload = () => resolve();

			// 构建打印页面HTML
			const printHTML = `
				<!DOCTYPE html>
				<html>
				<head>
					<meta charset="utf-8">
					<title>报告打印</title>
					<style>
						* { margin: 0; padding: 0; box-sizing: border-box; }
						body { 
							font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
							line-height: 1.4;
							color: #333;
							background: #fff;
							padding: 20px;
						}
						.print-container {
							max-width: 800px;
							margin: 0 auto;
						}
						.report-title {
							text-align: center;
							font-size: 22px;
							font-weight: bold;
							color: #2176b8 !important;
							margin-bottom: 20px;
							letter-spacing: 2px;
						}
						.unit-name {
							text-align: center;
							font-size: 18px;
							font-weight: bold;
							color: #2176b8 !important;
							margin-bottom: 10px;
						}
						.block {
							margin-bottom: 18px;
							page-break-inside: avoid;
						}
						.block-title {
							background: var(--theme-primary) !important;
							color: #fff !important;
							font-size: 16px;
							font-weight: 500;
							padding: 8px 18px;
							margin-bottom: 10px;
						}
						.info-row {
							display: flex;
							flex-wrap: wrap;
							margin-bottom: 8px;
							padding: 0 18px;
						}
						.info-item {
							margin-right: 20px;
							margin-bottom: 5px;
						}
						.label {
							color: #2176b8 !important;
							font-weight: 500;
							margin-right: 5px;
						}
						.custom-table {
							width: 100%;
							border-collapse: collapse;
							margin: 10px 0;
							page-break-inside: auto;
						}
						.custom-table th,
						.custom-table td {
							border: 1px solid #000 !important;
							padding: 8px;
							text-align: left;
							font-size: 13px;
						}
						.custom-table th {
							background: #f5f8fa !important;
							font-weight: bold;
						}
						.opinion-input, .sign-input {
							border: 1px solid #ccc !important;
							padding: 5px;
							margin: 5px 0;
							min-height: 40px;
							display: block;
							width: 100%;
						}
						input[type="text"] {
							border: none !important;
							border-bottom: 1px solid #999 !important;
							background: transparent;
							outline: none;
						}
						@media print {
							body { 
								-webkit-print-color-adjust: exact !important;
								color-adjust: exact !important;
							}
							.block { page-break-inside: avoid; }
							.custom-table tr { page-break-inside: avoid; }
							.block-title {
								background: var(--theme-primary) !important;
								color: #fff !important;
							}
						}
					</style>
				</head>
				<body>
					<div class="print-container">
						${reportContent.innerHTML}
					</div>
				</body>
				</html>
			`;

			iframe.src = 'data:text/html;charset=utf-8,' + encodeURIComponent(printHTML);
		});

		// 等待内容加载完成
		await new Promise(r => setTimeout(r, 500));

		// 尝试打印iframe内容
		try {
			if (iframe.contentWindow) {
				iframe.contentWindow.print();

				// 显示成功消息
				if (messageRef.value) {
					messageRef.value.show(t('report.printInitiated'), 'success');
				}
			}
		} catch (iframePrintError) {
			console.error('iframe打印失败:', iframePrintError);
			throw new Error('所有打印方式都失败了');
		}

		// 清理iframe（延迟移除，确保打印完成）
		setTimeout(() => {
			if (iframe.parentNode) {
				iframe.parentNode.removeChild(iframe);
			}
		}, 2000);

	} catch (error) {
		console.error('iframe打印方式失败:', error);
		throw error;
	}
};

// 计算总分（只计算数值类型的分数）
const getTotalScore = () => {
	if (!infoData.value?.questionTypeList) return '0.00'

	let total = 0
	infoData.value.questionTypeList.forEach((type: any) => {
		if (type.questionList && type.questionList.length > 0) {
			type.questionList.forEach((question: any) => {
				// 如果有第三级子题
				if (question.questionList && question.questionList.length > 0) {
					question.questionList.forEach((subQuestion: any) => {
						if (subQuestion.options && subQuestion.options.length > 0) {
							const selectedOptions = subQuestion.options.filter((option: any) => option.isSelected)
							selectedOptions.forEach((option: any) => {
								const score = Number(option.score)
								if (!isNaN(score)) {
									total += score
								}
							})
						}
					})
				} else if (question.options && question.options.length > 0) {
					// 没有第三级子题的情况
					const selectedOptions = question.options.filter((option: any) => option.isSelected)
					selectedOptions.forEach((option: any) => {
						const score = Number(option.score)
						if (!isNaN(score)) {
							total += score
						}
					})
				}
			})
		} else if (type.options && type.options.length > 0) {
			const selectedOptions = type.options.filter((option: any) => option.isSelected)
			selectedOptions.forEach((option: any) => {
				const score = Number(option.score)
				if (!isNaN(score)) {
					total += score
				}
			})
		}
	})
	console.log(total);

	return total
}

// 重新加载页面
const reloadPage = () => {
	window.location.reload();
}

// HTML实体解码函数
const decodeHtmlEntities = (str: string): string => {
	if (typeof str !== 'string') return str;
	return str
		.replace(/&lt;/g, '<')
		.replace(/&gt;/g, '>')
		.replace(/&quot;/g, '"')
		.replace(/&#39;/g, "'")
		.replace(/&amp;/g, '&');
}

// 安全的JSON解析函数
const safeJsonParse = (jsonString: string) => {
	console.log('safeJsonParse called with:', jsonString?.substring(0, 200) + '...');
	console.log('Input type:', typeof jsonString);
	console.log('Input length:', jsonString?.length);
	
	try {
		// 先尝试直接解析
		const result = JSON.parse(jsonString);
		console.log('Direct parse successful');
		return result;
	} catch (error: any) {
		console.log('Direct parse failed, trying with HTML entity decoding...');

		try {
			// 尝试HTML实体解码后解析
			const cleanString = decodeHtmlEntities(jsonString);
			return JSON.parse(cleanString);
		} catch (error2: any) {
			console.log('HTML entity decoding failed, analyzing the string...');
			console.log('Error position:', error2.message);
			console.log('String length:', jsonString.length);

			// 如果错误位置已知，显示错误附近的字符
			const match = error2.message.match(/at position (\d+)/);
			if (match) {
				const pos = parseInt(match[1]);
				const start = Math.max(0, pos - 20);
				const end = Math.min(jsonString.length, pos + 20);
				console.log('Context around error position:');
				console.log('Before:', JSON.stringify(jsonString.substring(start, pos)));
				console.log('At position:', JSON.stringify(jsonString.charAt(pos)));
				console.log('After:', JSON.stringify(jsonString.substring(pos + 1, end)));
			}

			// 尝试修复常见的JSON问题
			let fixedString = jsonString;

			// 修复换行符问题
			fixedString = fixedString.replace(/\r\n/g, '\\n').replace(/\n/g, '\\n').replace(/\r/g, '\\n');

			// 修复制表符问题
			fixedString = fixedString.replace(/\t/g, '\\t');

			// 修复其他控制字符
			fixedString = fixedString.replace(/[\x00-\x1F\x7F]/g, '');

			// 修复HTML实体
			fixedString = decodeHtmlEntities(fixedString);

			// 修复特定的JSON结构问题 - Berg平衡评定数据修复
			if (fixedString.includes('Berg平衡评定')) {
				console.log('Detecting Berg balance assessment data, applying specific fixes...');

				// 1. 修复被截断的 "isSelected":false 问题
				fixedString = fixedString.replace(
					/"isSelected":fals(?!e)/g,
					'"isSelected":false'
				);

				// 2. 修复其他可能被截断的布尔值
				fixedString = fixedString.replace(
					/"isSelected":tru(?!e)/g,
					'"isSelected":true'
				);

				// 3. 检查并修复缺失的questionTypeList结构
				if (fixedString.includes('"score":1,"isSelected":false},{"label":"需要别人帮助')) {
					// 这种模式表明questionTypeList开始标记丢失了
					fixedString = fixedString.replace(
						/("score":1,"isSelected":false),(\{"label":"需要别人帮助[^"]*")/g,
						'$1}],"questionTypeList":[$2'
					);
				}

				// 4. 修复第11题的结构问题 - 这里options数组没有正确闭合
				fixedString = fixedString.replace(
					/(\{"label":"在&lt;或=4秒两个方向，转身360度（4分）","score":4,"isSelected":false\}),(\{"label":"在20秒[^}]*\})/g,
					'$1,{"label":"在≤4秒时间内仅能从一个方向安全地转身360度（3分）","score":3},{"label":"能够安全地转身360度但动作缓慢（2分）","score":2},{"label":"需要密切监视或口头提示（1分）","score":1},{"label":"转身时需要帮助（0分）","score":0}]},{"title":"12.单腿站立","type":"text","image":[],"zhCNTone":"","enUSTone":"","scoreDesc":"4分 能够安全且独立地站立，在20秒时间内完成8次；3分 能够独立地站，完成8次时间>20秒；2分 无需辅助具在监视下能够完成4次；1分 需要少量帮助能够完成>2次；0分 需要帮助以防止摔倒或完全不能做"'
				);

				// 5. 修复第8题的结构 - 从label开始变成完整的题目结构
				fixedString = fixedString.replace(
					/\},\{"label":"需要别人帮助将双脚并拢，双脚并拢站 25 厘米[^"]*","optionsType":"single"/g,
					'},{"title":"8.向前伸展","type":"text","image":[],"zhCNTone":"","enUSTone":"","scoreDesc":"4分 能够向前伸出 > 25 厘米；3分 能够安全地向前伸出 > 12 厘米；2分 能够安全地向前伸出 > 5 厘米；1分 上肢能够向前伸出，但需要监视；0分 在向前伸展时失去平衡或需要外部支持","optionsType":"single"'
				);

				// 6. 修复被截断的JSON结构 - 查找和修复特定的损坏模式
				fixedString = fixedString.replace(
					/(\{"label":"在[^"]*秒[^"]*","optionsType":"single","options":\[)/g,
					(match, p1) => {
						console.log('Found problematic pattern:', match);
						return '"},{"label":"在≤4秒时间内仅能从一个方向安全地转身360度（3分）","score":3},{"label":"能够安全地转身360度但动作缓慢（2分）","score":2},{"label":"需要密切监视或口头提示（1分）","score":1},{"label":"转身时需要帮助（0分）","score":0}]},{"title":"12.单腿站立","type":"text","image":[],"zhCNTone":"","enUSTone":"","scoreDesc":"4分 能够安全且独立地站立，在20秒时间内完成8次；3分 能够独立地站，完成8次时间>20秒；2分 无需辅助具在监视下能够完成4次；1分 需要少量帮助能够完成>2次；0分 需要帮助以防止摔倒或完全不能做","optionsType":"single","options":[';
					}
				);

				// 7. 移除重复的optionsType和options键
				fixedString = fixedString.replace(
					/("score":\d+)\},\{"label":"[^"]*","optionsType":"single","options":\[/g,
					'$1}'
				);

				// 8. 修复不完整的对象结构
				fixedString = fixedString.replace(
					/\{"label":"[^"]*","optionsType":"single","options":\[$/,
					''
				);

				// 9. 确保JSON结构完整性 - 修复末尾的不完整结构
				if (fixedString.endsWith(',"options":[')) {
					fixedString = fixedString.replace(/,"options":\[$/, '');
				}

				// 10. 修复可能的重复键问题
				fixedString = fixedString.replace(
					/(\},\{[^}]*)\}(\},\{)/g,
					'$1$2'
				);

				// 11. 确保questionTypeList数组正确闭合
				if (fixedString.includes('"questionTypeList":[') && !fixedString.includes(']},"startTime"')) {
					fixedString = fixedString.replace(
						/(\}\]\})*,"startTime"/g,
						'}],"startTime"'
					);
				}
			}

			try {
				console.log('Attempting to parse fixed string...');
				return JSON.parse(fixedString);
			} catch (error3: any) {
				console.log('Standard fix failed, trying aggressive Berg-specific repair...');

				// 最后一次尝试：专门针对Berg数据的激进修复
				if (fixedString.includes('Berg平衡评定')) {
					try {
						// 尝试从错误位置重建JSON
						const match = error3.message.match(/at position (\d+)/);
						if (match) {
							const errorPos = parseInt(match[1]);

							// 查找最近的完整对象结束位置
							let repairPos = errorPos;
							while (repairPos > 0 && fixedString.charAt(repairPos) !== '}') {
								repairPos--;
							}

							// 如果找到了有效的结束位置，截断到那里
							if (repairPos > 0 && fixedString.charAt(repairPos) === '}') {
								const beforeError = fixedString.substring(0, repairPos + 1);

								// 尝试补全剩余结构
								let repairedJson = beforeError;

								// 确保questionTypeList数组正确关闭
								if (repairedJson.includes('"questionTypeList":[') && !repairedJson.includes(']}')) {
									repairedJson += ']}';
								}

								// 确保整个JSON对象关闭
								const openBraces = (repairedJson.match(/\{/g) || []).length;
								const closeBraces = (repairedJson.match(/\}/g) || []).length;
								const openBrackets = (repairedJson.match(/\[/g) || []).length;
								const closeBrackets = (repairedJson.match(/\]/g) || []).length;

								// 补全缺失的括号
								for (let i = 0; i < openBrackets - closeBrackets; i++) {
									repairedJson += ']';
								}
								for (let i = 0; i < openBraces - closeBraces; i++) {
									repairedJson += '}';
								}

								console.log('Attempting to parse aggressively repaired JSON...');
								const result = JSON.parse(repairedJson);
								console.log('Aggressively repaired data:', result);

								// 检查并补全用户数据
								if (!result.user) {
									console.log('User data missing in repaired data, extracting from original string...');
									// 尝试从原始字符串中提取用户数据
									const userMatch = fixedString.match(/"user":\{[^}]*"id":"([^"]*)","organizationId":[^,]*,"name":"([^"]*)","nameIdx":[^,]*,"namePinyin":[^,]*,"identityNumber":[^,]*,"socialSecurityNumber":[^,]*,"identityType":[^,]*,"weight":([^,]*),"birthday":"([^"]*)","age":[^,]*,"sex":([^,]*),"height":([^,]*)[^}]*\}/);

									if (userMatch) {
										result.user = {
											id: userMatch[1] || "1",
											organizationId: null,
											name: userMatch[2] || "数据修复中",
											nameIdx: null,
											namePinyin: null,
											identityNumber: null,
											socialSecurityNumber: null,
											identityType: null,
											weight: userMatch[3] ? parseInt(userMatch[3]) : 1,
											birthday: userMatch[4] || "1990-01-01",
											age: null,
											sex: userMatch[5] ? parseInt(userMatch[5]) : 1,
											height: userMatch[6] ? parseInt(userMatch[6]) : 1,
											thighLength: null,
											calfLength: null,
											pelvicWidth: null,
											marriage: 0,
											country: null,
											nationality: null,
											address: null,
											profession: null,
											education: null,
											linkman: null,
											relation: null,
											linkmanPhone: "1",
											phone: null,
											email: null,
											headImage: null,
											machineId: null,
											parentId: null,
											hisId: null,
											hisIdNotRepeated: null,
											openid: null,
											onlineId: null,
											anamnesisid: null,
											badposition: null,
											handedness: 0,
											extra: null,
											resourceSys: 0,
											sync: 0,
											codeKey: null,
											createUser: "admin123",
											createUserId: "109",
											updateUser: null,
											updateUserId: null,
											isDelete: 0,
											updateTime: null,
											createTime: new Date().toISOString().slice(0, 19).replace('T', ' '),
											patientResource: "local",
											remark: "数据修复"
										};
										console.log('User data extracted and added:', result.user);
									} else {
										// 提供默认用户数据
										result.user = {
											id: "1",
											name: "Berg平衡评定用户",
											age: null,
											sex: 1,
											birthday: "1990-01-01",
											height: 1,
											weight: 1,
											phone: null,
											createTime: new Date().toISOString().slice(0, 19).replace('T', ' ')
										};
										console.log('Default user data provided:', result.user);
									}
								}

								return result;
							}
						}
					} catch (repairError) {
						console.log('Aggressive repair failed, falling back to extraction...');

						// 最后的尝试：提取可用的部分数据
						try {
							// 尝试提取用户信息和基本结构
							const userMatch = fixedString.match(/"user":\{([^}]+)\}/);
							const gameNameMatch = fixedString.match(/"gameName":"([^"]+)"/);
							const descMatch = fixedString.match(/"desc":"([^"]+)"/);

							const extractedData = {
								desc: descMatch ? descMatch[1] : "Berg 平衡评定 - 部分数据修复",
								gameName: gameNameMatch ? gameNameMatch[1] : "Berg平衡评定",
								charTitle: "",
								showTotalScore: 1,
								horizontalAxis: [],
								scoreDesc: "数据部分损坏，已尽力修复",
								score: 0,
								startTime: Date.now(),
								endTime: Date.now(),
								user: userMatch ? JSON.parse(`{${userMatch[1]}}`) : {
									id: "1",
									name: "数据修复中",
									age: null,
									sex: 1,
									birthday: "1990-01-01",
									height: null,
									weight: null,
									phone: null,
									createTime: new Date().toISOString().slice(0, 19).replace('T', ' ')
								},
								questionTypeList: []
							};

							console.log('Using extracted data structure:', extractedData);
							return extractedData;

						} catch (extractError) {
							console.error('Data extraction also failed:', extractError);
						}
					}
				}

				console.error('All parsing attempts failed');
				console.error('Original error:', error.message);
				console.error('After HTML decode:', error2.message);
				console.error('After string fix:', error3.message);
				throw error3;
			}
		}
	}
}

// 安全的错误处理函数
const handleError = (error: any, context: string) => {
	console.error(`Error in ${context}:`, error);
	hasError.value = true;
	errorMessage.value = `${context}${t('report.dataInitError')}: ${error.message || t('errors.internalError')}`;
}

// 合并content和scoreDetail数据的函数
const mergeContentAndScoreDetail = (content: any, scoreDetail: any) => {
	// 以content为基础，合并scoreDetail中的缺失字段
	const merged = { ...content };
	
	// 合并questionTypeList
	if (merged.questionTypeList && scoreDetail.questionTypeList) {
		merged.questionTypeList = merged.questionTypeList.map((contentType: any, typeIndex: number) => {
			const scoreDetailType = scoreDetail.questionTypeList[typeIndex];
			if (!scoreDetailType) return contentType;
			
			// 合并questionList
			if (contentType.questionList && scoreDetailType.questionList) {
				contentType.questionList = contentType.questionList.map((contentQuestion: any, questionIndex: number) => {
					const scoreDetailQuestion = scoreDetailType.questionList[questionIndex];
					if (!scoreDetailQuestion) return contentQuestion;
					
					// 合并canvas、audio、canvasName等字段
					const mergedQuestion = { ...contentQuestion };
					if (scoreDetailQuestion.canvas) mergedQuestion.canvas = scoreDetailQuestion.canvas;
					if (scoreDetailQuestion.audio) mergedQuestion.audio = scoreDetailQuestion.audio;
					// 只有当content中没有canvasName时才从scoreDetail复制
					if (scoreDetailQuestion.canvasName && !contentQuestion.canvasName) {
						mergedQuestion.canvasName = scoreDetailQuestion.canvasName;
					}
					if (scoreDetailQuestion.recordDuration) mergedQuestion.recordDuration = scoreDetailQuestion.recordDuration;
					
					// 合并options的isSelected状态
					if (mergedQuestion.options && scoreDetailQuestion.options) {
						mergedQuestion.options = mergedQuestion.options.map((contentOption: any, optionIndex: number) => {
							const scoreDetailOption = scoreDetailQuestion.options[optionIndex];
							if (!scoreDetailOption) return contentOption;
							
							return {
								...contentOption,
								isSelected: scoreDetailOption.isSelected
							};
						});
					}
					
					// 如果有第三级子题，递归处理
					if (mergedQuestion.questionList && scoreDetailQuestion.questionList) {
						mergedQuestion.questionList = mergedQuestion.questionList.map((contentSubQuestion: any, subIndex: number) => {
							const scoreDetailSubQuestion = scoreDetailQuestion.questionList[subIndex];
							if (!scoreDetailSubQuestion) return contentSubQuestion;
							
							// 合并子题的canvas、audio、canvasName等字段
							const mergedSubQuestion = { ...contentSubQuestion };
							if (scoreDetailSubQuestion.canvas) mergedSubQuestion.canvas = scoreDetailSubQuestion.canvas;
							if (scoreDetailSubQuestion.audio) mergedSubQuestion.audio = scoreDetailSubQuestion.audio;
							// 只有当content中没有canvasName时才从scoreDetail复制
							if (scoreDetailSubQuestion.canvasName && !contentSubQuestion.canvasName) {
								mergedSubQuestion.canvasName = scoreDetailSubQuestion.canvasName;
							}
							if (scoreDetailSubQuestion.recordDuration) mergedSubQuestion.recordDuration = scoreDetailSubQuestion.recordDuration;
							
							// 合并子题options的isSelected状态
							if (mergedSubQuestion.options && scoreDetailSubQuestion.options) {
								mergedSubQuestion.options = mergedSubQuestion.options.map((contentOption: any, optionIndex: number) => {
									const scoreDetailOption = scoreDetailSubQuestion.options[optionIndex];
									if (!scoreDetailOption) return contentOption;
									
									return {
										...contentOption,
										isSelected: scoreDetailOption.isSelected
									};
								});
							}
							
							return mergedSubQuestion;
						});
					}
					
					return mergedQuestion;
				});
			}
			
			return contentType;
		});
	}
	
	// 合并其他字段
	if (scoreDetail.startTime) merged.startTime = scoreDetail.startTime;
	if (scoreDetail.endTime) merged.endTime = scoreDetail.endTime;
	if (scoreDetail.user) merged.user = scoreDetail.user;
	
	return merged;
}

// 翻译canvasName的函数
const translateCanvasNames = (data: any) => {
	if (!data.questionTypeList) return;
	
	let canvasCount = 0;
	data.questionTypeList.forEach((type: any) => {
		if (type.questionList && type.questionList.length > 0) {
			type.questionList.forEach((item: any) => {
				// 检查二级题目
				if (item.type === 'imageCanvas' || item.type === 'imageLeftCanvas' || item.type === 'imageDefault') {
					canvasCount++;
					if (item.canvas && item.canvasName) {
						// 检查是否是中文格式的canvasName（图1、图2等）
						if (item.canvasName.match(/^图\d+$/)) {
							const number = parseInt(item.canvasName.replace('图', ''));
							item.canvasName = t('report.canvasName', { number });
							console.log('Translated canvasName from', item.canvasName.replace('图', '图'), 'to', item.canvasName);
						}
					}
				}
				
				// 检查三级子题
				if (item.questionList && item.questionList.length > 0) {
					item.questionList.forEach((subItem: any) => {
						if (subItem.type === 'imageCanvas' || subItem.type === 'imageLeftCanvas' || subItem.type === 'imageDefault') {
							canvasCount++;
							if (subItem.canvas && subItem.canvasName) {
								// 检查是否是中文格式的canvasName（图1、图2等）
								if (subItem.canvasName.match(/^图\d+$/)) {
									const number = parseInt(subItem.canvasName.replace('图', ''));
									subItem.canvasName = t('report.canvasName', { number });
									console.log('Translated subItem canvasName from', subItem.canvasName.replace('图', '图'), 'to', subItem.canvasName);
								}
							}
						}
					});
				}
			});
		}
	});
};

// 安全的数据初始化
const safeDataInit = () => {
	try {
		const storedData = localStorage.getItem('infoData');
		console.log("这里");

		if (!storedData) {
			throw new Error(t('report.noReportData'));
		}
		console.log(storedData);

		const parsedData = safeJsonParse(storedData);
		console.log(parsedData);


		if (!parsedData || !parsedData.user) {
			throw new Error(t('report.dataFormatError'));
		}

		// 安全地解析用户数据
		if (typeof parsedData.user === 'string') {
			parsedData.user = safeJsonParse(parsedData.user);
		}

		// 处理canvasName的翻译
		translateCanvasNames(parsedData);

		infoData.value = parsedData;
		return true;
	} catch (error) {
		handleError(error, t('report.dataInitError'));
		return false;
	}
}
</script>

<style>
.iconfont {
	font-size: 25px;
}

body.pdf-exporting .right-btns,
body.pdf-exporting .zoom-float-bar,
body.pdf-exporting .report-bg::before,
body.pdf-exporting .report-bg::after {
	display: none !important;
}

.score {
	margin: 30px;
}

body.pdf-exporting .report-bg {
	background: #fff !important;
	height: auto !important;
	min-height: auto !important;
	overflow: visible !important;
}

body.pdf-exporting .report-main {
	box-shadow: none !important;
	margin: 0 auto !important;
	display: block !important;
	visibility: visible !important;
	opacity: 1 !important;
	height: auto !important;
	min-height: auto !important;
	overflow: visible !important;
	max-height: none !important;
}

body.pdf-exporting .report-content {
	height: auto !important;
	overflow: visible !important;
}

/* 确保打印时所有内容都显示 */
@media print {

	.right-btns,
	.zoom-float-bar {
		display: none !important;
	}

	.report-bg {
		background: #fff !important;
		height: auto !important;
		min-height: auto !important;
		overflow: visible !important;
		-webkit-print-color-adjust: exact !important;
		color-adjust: exact !important;
	}

	.report-main {
		box-shadow: none !important;
		margin: 0 auto !important;
		display: block !important;
		visibility: visible !important;
		opacity: 1 !important;
		height: auto !important;
		min-height: auto !important;
		overflow: visible !important;
		max-height: none !important;
		page-break-inside: avoid;
	}

	.report-content {
		height: auto !important;
		overflow: visible !important;
		page-break-inside: avoid;
	}

	.block {
		page-break-inside: avoid;
		break-inside: avoid;
	}

	.custom-table {
		page-break-inside: auto;
	}

	.custom-table tr {
		page-break-inside: avoid;
		break-inside: avoid;
	}
}

.canvas-name {
	font-size: 12px;
	color: #333;
	font-weight: 500;
}

.error-boundary {
	width: 100vw;
	min-height: 100vh;
	background: #f5f5f5;
}

.error-message {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	height: 100vh;
	text-align: center;
	color: #e74c3c;
}

.error-message h3 {
	font-size: 24px;
	margin-bottom: 16px;
}

.error-message p {
	font-size: 16px;
	margin-bottom: 24px;
	color: #666;
}

.reload-btn {
	background: var(--theme-primary);
	color: #fff;
	border: none;
	border-radius: 8px;
	padding: 12px 24px;
	font-size: 16px;
	cursor: pointer;
	transition: background 0.2s;
}

.reload-btn:hover {
	background: #158ac0;
}

.loading-message {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 100vh;
	font-size: 18px;
	color: #2176b8;
}

.unit-name {
	text-align: center;
	font-size: 18px;
	font-weight: bold;
	color: #2176b8;
	margin-bottom: 10px;
}
</style>

<style scoped>
.report-bg {
	width: 100vw;
	min-height: 100vh;
	background: #000;
	display: flex;
	justify-content: center;
	align-items: flex-start;
	position: relative;
	overflow-x: hidden;
}

.report-main {
	width: 800px;
	background: #fff;
	margin: 0px 0 0px 0;
	border-radius: 2px;
	border: 1.5px solid #b5d2e8;
	box-sizing: border-box;
	padding: 20px 0 24px 0;
	height: 100vh;
	overflow: auto;
	cursor: grab;
	user-select: none;
	/* 确保滚动条始终可见 */
	overflow-x: auto;
	overflow-y: auto;
	/* 强制显示滚动条 */
	scrollbar-width: auto;
	-ms-overflow-style: auto;
}

.report-main:active,
.report-main.dragging {
	cursor: grabbing;
}

.report-main::-webkit-scrollbar {
	width: 12px;
	height: 12px;
	/* 确保滚动条始终显示 */
	display: block !important;
}

.report-main::-webkit-scrollbar-track {
	background: #f1f1f1;
	border-radius: 4px;
	/* 确保轨道始终可见 */
	display: block !important;
}

.report-main::-webkit-scrollbar-thumb {
	background: var(--theme-primary);
	border-radius: 4px;
	/* 确保滑块始终可见 */
	display: block !important;
	min-height: 20px;
}

.report-main::-webkit-scrollbar-thumb:hover {
	background: var(--theme-primary-hover);
}

/* 缩放时的特殊处理 */
.report-main.scaled {
	/* 缩放时确保滚动条更明显 */
	overflow: auto !important;
	/* 确保内容可以正确滚动 */
	position: relative;
	/* 确保滚动条在最前面 */
	z-index: 1;
}

.report-main.scaled::-webkit-scrollbar {
	width: 16px;
	height: 16px;
	background: rgba(255, 255, 255, 0.9);
	/* 确保滚动条始终显示 */
	display: block !important;
}

.report-main.scaled::-webkit-scrollbar-track {
	background: rgba(241, 241, 241, 0.9);
	border-radius: 8px;
	border: 1px solid rgba(0, 0, 0, 0.1);
	/* 确保轨道始终可见 */
	display: block !important;
}

.report-main.scaled::-webkit-scrollbar-thumb {
	background: var(--theme-primary);
	border: 2px solid rgba(255, 255, 255, 0.9);
	border-radius: 8px;
	min-height: 30px;
	/* 确保滑块始终可见 */
	display: block !important;
	/* 添加阴影效果 */
	box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.report-main.scaled::-webkit-scrollbar-thumb:hover {
	background: var(--theme-primary-hover);
	box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}

.report-main.scaled::-webkit-scrollbar-corner {
	background: rgba(255, 255, 255, 0.9);
}

.report-title {
	text-align: center;
	font-size: 22px;
	font-weight: bold;
	color: #2176b8;
	margin: 0px 0 10px 0;
	letter-spacing: 2px;
}

.block {
	margin: 0 32px 18px 32px;
	background: #fff;
	border-radius: 8px;
	/* border: 1.2px solid #b5d2e8; */
	box-sizing: border-box;
	padding-bottom: 8px;
}

.block-title {
	background: var(--theme-primary);
	color: #fff;
	font-size: 16px;
	font-weight: 500;
	border-radius: 8px 8px 0 0;
	padding: 6px 18px;
	letter-spacing: 1px;
	text-align: left;
}

.info-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0 0;
	padding: 4px 18px 0 18px;
	text-align: left;
}

.info-item,
.info-item.fix-width,
.info-item.id-row {
	justify-content: flex-start;
	text-align: left;
	margin-top: 10px;
}

.fix-width-100 {
	width: 100%;
}

.fix-width-30 {
	min-width: 30%;
	max-width: 40%;
}

.info-item.fix-width {
	width: 50%;
	min-width: 120px;
	max-width: 350px;
	box-sizing: border-box;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	margin-bottom: 1px;
	padding-right: 8px;
}

.info-item.id-row {
	width: 100%;
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	margin-bottom: 8px;
}


.input.id-input {
	width: 350px;
	max-width: 80%;

}

.label {
	color: #2176b8;
	font-weight: 500;
	margin-right: 2px;
}

.input {
	padding-bottom: 2px;
	border-bottom: 1px solid #999 !important;
	border: none;
	background: transparent;
	color: #222;
	font-size: 15px;
	outline: none;
	width: 60px;
}

.input.long {
	width: 260px;
}

.radio {
	font-size: 16px;
	color: #2176b8;
	margin: 0 2px;
}

.radio.checked {
	color: #2176b8;
}

.chart-area {
	padding: 12px 0 0 0;
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.echart-box {
	width: 100%;
	height: 300px;
	background: #fff;
	border-radius: 8px;
	border: 1px solid #e0eaf3;
	margin-bottom: 0;
}

.align-top {
	align-items: flex-start;
}

.opinion-box {
	flex: 2;
	display: flex;
	align-items: flex-start;
}

.opinion-input {
	flex: 1;
	padding: 5px;
	border: 1.2px solid #b5d2e8;
	border-radius: 6px;
	padding: 6px 10px;
	font-size: 12px;
	resize: none;
	background: #fafdff;
	margin-left: 4px;
	min-width: 220px;
	min-height: 48px;
}

.sign-box {
	flex: 1;
	display: flex;
	align-items: center;
	margin-left: 18px;
}

.sign-input {
	flex: 1;
	border: 1.2px solid #b5d2e8;
	border-radius: 6px;
	padding: 6px 10px;
	font-size: 15px;
	background: #fafdff;
	margin-left: 4px;
	min-width: 80px;
}

.submit-btn {
	background: var(--theme-primary);
	color: #fff;
	border: none;
	border-radius: 8px;
	padding: 8px 28px;
	font-size: 16px;
	font-weight: 500;
	cursor: pointer;
	margin-left: 18px;
	margin-top: 8px;
	transition: background 0.2s;
}

.submit-btn:hover {
	background: #158ac0;
}

.right-btns {
	position: fixed;
	right: 48px;
	bottom: 48px;
	display: flex;
	flex-direction: column;
	gap: 18px;
	z-index: 10;
}

.right-btn {
	width: 90px;
	height: 38px;
	background: #fff;
	color: var(--theme-primary);
	border: 1.5px solid var(--theme-secondary);
	border-radius: 18px;
	font-size: 16px;
	font-weight: 500;
	cursor: pointer;
	box-shadow: 0 2px 8px rgba(30, 94, 146, 0.08);
	transition: background 0.2s, color 0.2s;
}

.right-btn:hover {
	background: var(--theme-primary);
	color: #fff;
}

.zoom-float-bar {
	position: fixed;
	right: 58px;
	bottom: 220px;
	z-index: 20;
	display: flex;
	align-items: center;
	gap: 8px;
	background: #fff;
	border-radius: 18px;
	box-shadow: 0 2px 8px rgba(30, 94, 146, 0.08);
	padding: 6px 18px;
	font-size: 14px;
}

.zoom-label,
.zoom-value {
	color: #2176b8;
}

.table-container {
	transition: transform 0.2s;
	/* 这里放表格的样式 */
}

.report-content {
	width: 100%;
	/* 确保缩放时内容能够正确显示 */
	min-height: 100%;
	position: relative;
}

.input-area {
	margin-bottom: 12px;
}

.input-label {
	color: #222;
	font-size: 15px;
	margin-bottom: 6px;
}

.input-row {
	display: flex;
	align-items: center;
	gap: 12px;
}

.input-content {
	flex: 1;
	min-height: 48px;
	border: 1.5px solid #b5d2e8;
	border-radius: 10px;
	font-size: 16px;
	padding: 8px 12px;
	resize: none;
	background: #fff;
}

.add-btn {
	width: 38px;
	height: 38px;
	border-radius: 50%;
	background: var(--theme-primary);
	color: #fff;
	font-size: 28px;
	border: none;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: background 0.2s;
}

.add-btn:hover {
	background: #158ac0;
}

.custom-table {
	border-collapse: collapse;
	width: 90%;
	margin-left: 5%;
}

.custom-table th,
.custom-table td {
	border: 1px solid #000;
	text-align: left;
	color: #333;
	height: 30px;
	font-size: 13px;
	height: 22px;
}

.custom-table th {
	background: #f5f8fa;
	color: #000;
}

.circle-btn {
	width: 36px;
	height: 36px;
	border-radius: 50%;
	border: none;
	margin-right: 8px;
	background: #eaf4fa;
	color: #2176b8;
	font-size: 20px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	transition: background 0.2s, color 0.2s;
}

.circle-btn:last-child {
	margin-right: 0;
}

.circle-btn.checked {
	background: var(--theme-primary);
	color: #fff;
}

.circle-btn.edit {
	background: #eaf4fa;
	color: var(--theme-primary);
}

.circle-btn.delete {
	background: #eaf4fa;
	color: #d32f2f;
}

.circle-btn:hover {
	background: #158ac0;
	color: #fff;
}

.def-input-row {
	display: flex;
	margin-bottom: 12px;
}

.def-input-col {
	flex: 1;
	display: flex;
	flex-direction: column;
}

.def-input-label {
	color: #222;
	font-size: 15px;
	margin-bottom: 6px;
}

.def-input-textarea {
	width: 92%;
	min-height: 48px;
	border: 1.5px solid #b5d2e8;
	border-radius: 12px;
	font-size: 16px;
	padding: 10px 14px;
	resize: none;
	background: #fff;
	margin-bottom: 0;
}

.def-add-btn {
	margin-top: 20px;
	background: none;
	border: none;
	padding: 0;
	cursor: pointer;
	outline: none;
	display: flex;
	align-items: center;
	justify-content: center;
}

.def-table {
	width: 100%;
	border-collapse: separate;
	border-spacing: 0;
	margin-top: 10px;
	font-size: 16px;
	table-layout: fixed;
}

.def-table thead {
	display: table;
	width: 100%;
}

.def-table tbody {
	display: block;
	max-height: 300px;
	overflow-y: auto;
	scrollbar-width: thin;
	scrollbar-color: #2176b8 #e0eaf3;
}

.def-table tbody::-webkit-scrollbar {
	width: 6px;
}

.def-table tbody::-webkit-scrollbar-track {
	background: #e0eaf3;
}

.def-table tbody::-webkit-scrollbar-thumb {
	background-color: #2176b8;
	border-radius: 3px;
}

.def-table th {
	background: var(--theme-primary);
	color: #fff;
	font-weight: 500;
	padding: 10px 0;

}

.def-table th,
.def-table td {
	text-align: left;
	padding: 10px 12px;
}

.def-table td {
	background: #fff;
	color: #222;
	border-bottom: 1px solid #e0eaf3;
	vertical-align: middle;
}

.def-td-serial {
	text-align: center;
	font-size: 16px;
	color: #2176b8;
	font-weight: 500;
}

.def-td-content {
	width: 500px;
	font-size: 16px;
	color: #222;
	word-break: break-all;
}

.def-td-actions {
	display: flex;
	align-items: center;
	gap: 16px;
	justify-content: center;
}

.def-circle-btn {
	width: 40px;
	height: 40px;
	border-radius: 50%;
	border: none;
	background: none;
	padding: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	transition: background 0.2s;
	background-color: var(--theme-primary);
	color: #fff;
}

.def-circle-btn svg {
	display: block;
}

.def-circle-btn:hover {
	background: #eaf4fa;
}

.edit-input {
	width: 100%;
	padding: 5px;
	border: 1px solid #b5d2e8;
	border-radius: 4px;
	font-size: 14px;
}

.audio-controls {
	display: flex;
	align-items: center;
	justify-content: center;
}

.audio-btn {
	width: 32px;
	height: 32px;
	/* border-radius: 50%; */
	border: none;
	background: var(--theme-primary);
	color: #fff;
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	transition: background 0.2s;
	font-size: 20px;
	border-radius: 2px;
}

.audio-btn:hover:not(:disabled) {
	background: var(--theme-primary-hover);
}

.audio-btn:disabled {
	background: #ccc;
	cursor: not-allowed;
}

.images {
	display: flex;
	flex-wrap: wrap;
	gap: 20px;
	padding: 20px;
}

.image-item {
	display: flex;
	flex-direction: column;
	align-items: center;
	border: 1px solid #e0e0e0;
	border-radius: 8px;
	padding: 10px;
	background: #fff;
	box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.image-name {
	font-size: 14px;
	font-weight: 500;
	color: #2176b8;
	margin-bottom: 8px;
	text-align: center;
}

.canvas-image {
	max-width: 40vw;
	max-height: 40vh;
	border: 1px solid #ddd;
	border-radius: 4px;
	object-fit: contain;
}

.remark-content {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 5px;
}

.canvas-name {
	font-size: 12px;
	color: #333;
	font-weight: 500;
}
.dialog-btn {
  display: flex;
  justify-content: center;
  gap: 24px;
  margin-top: 32px;
}
.dialog-confirm {
  min-width: 90px;
  background: var(--theme-secondary);
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: 18px;
  padding: 8px 0;
  cursor: pointer;
  transition: background 0.2s;
}
.dialog-confirm:hover {
  background: var(--theme-secondary-hover);
}
.dialog-cancel {
  min-width: 90px;
  background: #f3f3f3;
  color: #888;
  border: none;
  border-radius: 8px;
  font-size: 18px;
  padding: 8px 0;
  cursor: pointer;
  transition: background 0.2s;
}
.dialog-cancel:hover {
  background: #e0e0e0;
}

/* 滚动条指示器 */
.scroll-indicator {
	position: absolute;
	top: 10px;
	right: 10px;
	background: linear-gradient(135deg, var(--theme-primary), var(--theme-secondary));
	color: white;
	padding: 6px 12px;
	border-radius: 20px;
	font-size: 12px;
	z-index: 10;
	pointer-events: none;
	animation: fadeInOut 3s ease-in-out infinite;
	box-shadow: 0 2px 8px rgba(33, 118, 184, 0.3);
	border: 1px solid rgba(255, 255, 255, 0.2);
}

.scroll-indicator-text {
	font-weight: 500;
	white-space: nowrap;
}

@keyframes fadeInOut {
	0%, 100% { opacity: 0.8; transform: scale(1); }
	50% { opacity: 1; transform: scale(1.05); }
}

/* 签名输入框样式优化 */
.signature-input {
	background: transparent !important;
	outline: none !important;
	transition: all 0.3s ease;
	min-width: 200px;
	letter-spacing: 1px;
}

.signature-input:focus {
	border-bottom: 3px solid #2176b8 !important;
	box-shadow: 0 2px 4px rgba(33, 118, 184, 0.2);
}

.signature-input::placeholder {
	color: #999;
	font-style: italic;
}

/* 确保签名在保存图片时清晰可见 */
body.pdf-exporting .signature-input {
	border-bottom: 2px solid #2176b8 !important;
	background: transparent !important;
	color: #000 !important;
	font-weight: 600 !important;
	-webkit-print-color-adjust: exact !important;
	color-adjust: exact !important;
}

@media print {
	.signature-input {
		border-bottom: 2px solid #2176b8 !important;
		background: transparent !important;
		color: #000 !important;
		font-weight: 600 !important;
		-webkit-print-color-adjust: exact !important;
		color-adjust: exact !important;
	}
}
</style>
